home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs49.d81 / hack10e.sfx / issue10e
Text File  |  1990-02-12  |  97KB  |  2,581 lines

  1. ╘HE FILE INFORMATION IS THE SAME AS FOR OPENING AN UPLOAD FILE, EXCEPT THAT
  2. THERE ARE MORE POSSIBLE RETURN CONDITIONS, AND ALL OF THE "META DATA" FIELDS
  3. ARE ACTUALLY FILLED IN BY THE ╒NIX HOST (SINCE THIS INFORMATION IS ACTUALLY
  4. CONVENIENTLY AVAILABLE VIA THE "STAT" SYSTEM CALL).
  5.  
  6. ╔F THE SERVER REPLIES WITH A '0' "DATA TYPE" CODE, THEN THIS MEANS THAT THE
  7. SERVER HAS NO MORE FILES TO OFFER FOR DOWNLOADING.  ╘HE FILENAMES TO DOWNLOAD
  8. ARE TAKEN ONE AT A TIME, FROM LEFT TO RIGHT, FROM THE COMMAND LINE THAT WAS
  9. USED TO START THE SERVER.  ╫HEN THE SERVER RUNS OUT, THEN THE DOWNLOADING
  10. SESSION IS COMPLETE AND THE CLIENT DISCONNECTS (SINCE THE CLIENT UPLOADS
  11. ITS FILES FIRST).
  12.  
  13. ┴LTERNATIVELY, THE SERVER COULD REPLY WITH A 'E' CODE, WHICH MEANS THAT
  14. IT COULD NOT OPEN THE NEXT FILENAME GIVEN ON ITS COMMAND LINE.  ┴N ERROR
  15. RETURN IS GENERATED SO THAT THE CLIENT CAN INFORM THE USER THAT THE FILE
  16. COULD NOT BE DOWNLOADED.  ╘HIS WILL NORMALLY RESULT FROM THE USER GIVING
  17. A BAD FILENAME ON THE COMMAND LINE.  ╘HE CLIENT WILL CONTINUE THE DOWNLOADING
  18. PROCESS BY CLOSING THE DOWNLOAD CHANNEL (BELOW) ASKING FOR THE NEXT FILE BY
  19. RE-OPENING THE DOWNLOAD CHANNEL.  ╘HE DOWNLOAD CHANNEL NEEDS TO BE CLOSED
  20. ON THIS CONDITION SINCE OTHERWISE THERE WOULD BE NO WAY OF DISTINGUISHING
  21. RETRANSMISSIONS FROM NEW REQUESTS AT THE SERVER.
  22.  
  23. ╞INALLY, THE SERVER CAN REPLY WITH A 'T' OR 'B' CODE ('D' FOR DIRECTORIES IS
  24. NOT CURRENTLY IMPLEMENTED) INDICATING THAT THE FILE WAS CORRECTLY OPENED AND
  25. IS EITHER TEXT OR BINARY (AS SPECIFIED ON THE SERVER'S COMMAND LINE).  ╧F THE
  26. META INFORMATION ABOUT THE FILE, ONLY THE FILENAME AND FILE SIZE ARE CURRENTLY
  27. USED: THE FILE IS NAMED ACCORDING TO THE GIVEN NAME, TRANSLATED TO ╨┼╘╙├╔╔ AND
  28. TRUNCATED TO 16 CHARACTERS, AND THE FILE SIZE IS REPORTED TO THE USER SO THAT
  29. HE CAN MONITOR DOWNLOADING PROGRESS.  ╔ AM NOT SURE WHAT TO DO YET ABOUT NAME
  30. COLLISIONS ON THE ├OMMODORE END: EITHER ASK THE USER WHETHER TO OVERWRITE THE
  31. FILE, AUTOMATICALLY OVERWRITE THE FILE ANYWAY, OR AUTOMATICALLY GIVE THE FILE
  32. A SLIGHTLY DIFFERENT NAME AND DOWNLOAD NORMALLY.  ╔ THINK THAT FOR THE TIME
  33. BEING, ╔ WILL JUST OVERWRITE THE EXISTING FILE.  ╘HIS WILL MEAN THAT YOU'LL
  34. WANT TO BE EXTRA CAREFUL IN PUTTING THE FILENAMES ONTO THE CORRECT COMMAND
  35. LINE (THE CLIENT'S OR THE SERVER'S), ALTHOUGH THERE WON'T BE A PROBLEM IF THE
  36. FILE DOESN'T EXIST ON THE MACHINE WHOSE COMMAND LINE YOU PUT THE NAME ON.
  37.  
  38. ╫HEN THE FILE HANDLING IS ALL SQUARED AWAY AND THE DOWNLOAD CHANNEL IS OPENED,
  39. THE CLIENT THEN SUCKS PACKETS OUT OF THE FILE UNTIL THE END OF THE FILE IS
  40. REACHED.  ╘HE PACKETS ARE SUCKED OUT WITH THE FOLLOWING REQUEST:
  41.  
  42. ╧╞╞   ╙╔┌   ─┼╙├
  43. ---   ---   -----
  44.   0     1   CODE: ╥┼╤_─╧╫╬╠╧┴─_╨┴├╦┼╘ ('╙')
  45.   1     1   DOWNLOAD SEQUENCE NUMBER
  46.   2     4   MAXIMUM ACCEPTABLE DATA LENGTH: ╚/═/═/╠ WORD
  47.   6     -   ╙╔┌┼
  48.  
  49. ╘HE "DOWNLOAD SEQUENCE NUMBER" IS USED TO DISTINGUISH RETRANSMISSIONS FROM
  50. REQUESTS FOR NEW PACKETS, AND THE CLIENT TELLS THE SERVER THE "MAXIMUM
  51. ACCEPTABLE DATA LENGTH" FOR THE REPLY PACKET.  ┴LTHOUGH THE MAX-PACKET
  52. INFORMATION IS ACTUALLY STATIC DURING THE CONNECTION, ╔ INCLUDED IT HERE IN
  53. EVERY "READ" REQUEST SINCE ╔ DIDN'T REALLY WANT THE SERVER TO KEEP THAT
  54. PARTICULAR BIT OF "STATE" INTERNALLY.
  55.  
  56. ╘HE SERVER REPLIES TO THE DOWNLOAD-PACKET REQUEST WITH THE FOLLOWING MESSAGE:
  57.  
  58. ╧╞╞   ╙╔┌   ─┼╙├
  59. ---   ---   -----
  60.   0     1   CODE: ┴├╦_─╧╫╬╠╧┴─_╨┴├╦┼╘ ('S')
  61.   1     1   DOWNLOAD SEQUENCE NUMBER
  62.   2     4   DATA LENGTH: ╚/═/═/╠ WORD, 0==┼╧╞
  63.   6     N   DATA
  64. 6+N     -   ╙╔┌┼
  65.  
  66. ╘HIS IS THE ONLY "LARGE" MESSAGE THAT THE SERVER CAN PRODUCE.  ╔T INCLUDES THE
  67. SEQUENCE NUMBER, THE NUMBER OF BYTES THAT ARE ACTUALLY INCLUDED, AND THE USER
  68. DATA.  ╘HE NUMBER OF DATA BYTES IN THE PACKET IS ALLOWED TO BE SMALLER THAN
  69. THE NUMBER OF BYTES REQUESTED, BUT THIS IS NORMALLY ONLY THE CASE FOR THE LAST
  70. PACKET OF THE FILE.
  71.  
  72. ╘O INDICATE THAT THE END OF FILE HAS BEEN REACHED AND THAT NO MORE USER DATA
  73. IS AVAILABLE, THE SERVER WILL RETURN A DOWNLOAD PACKET WITH ZERO BYTES OF USER
  74. DATA IN IT.  ╒PON RECEIVING THIS, THE CLIENT WILL CLOSE THE DOWNLOAD CHANNEL
  75. WITH THE FOLLOWING MESSAGE:
  76.  
  77. ╧╞╞   ╙╔┌   ─┼╙├
  78. ---   ---   -----
  79.   0     1   CODE: ╥┼╤_─╧╫╬╠╧┴─_├╠╧╙┼ ('┼')
  80.   1     -   ╙╔┌┼
  81.  
  82. ┴ND THE SERVER WILL REPLY WITH:
  83.  
  84. ╧╞╞   ╙╔┌   ─┼╙├
  85. ---   ---   -----
  86.   0     1   CODE: ┴├╦_─╧╫╬╠╧┴─_├╠╧╙┼ ('E')
  87.   1     4   NUMBER OF FILE BYTES DOWNLOADED: ╚/═/═/╠ WORD
  88.   5     -   ╙╔┌┼
  89.  
  90. ╘HE "NUMBER OF FILE BYTES DOWNLOADED" FIELD IS REDUNDANT BUT INCLUDED FOR
  91. ADDITIONAL ERROR CHECKING.  ┴FTER CLOSING A FILE, THE CLIENT WILL THEN ASK
  92. FOR THE NEXT FILE, OR WILL DISCONNECT IF THE LAST FILE TO DOWNLOAD WAS JUST
  93. CLOSED.
  94.  
  95. 4.4. ┼╥╥╧╥ ╚┴╬─╠╔╬╟
  96.  
  97. ╫ITH ALL OF THE SERVER CALLS EXCEPT FOR DISCONNECTING (DISCUSSED EARLIER), THE
  98. IS THE POSSIBILITY THAT EITHER THE REQUEST MESSAGE FROM THE CLIENT OR THE
  99. REPLY MESSAGE FROM THE SERVER WILL BECOME GARBLED AND BE DROPPED BY THE
  100. PACKET-DELIVERY LAYER OF THE SOFTWARE.  ╘O RECOVER FROM THIS, IF THE CLIENT
  101. DETECTS AN EXTENDED PERIOD OF INACTIVITY ON THE SERIAL LINE FOR RECEIVED DATA
  102. (WHERE "EXTENDED PERIOD" IS DEFINED AS BEING "ABOUT FIVE SECONDS"), THEN THE
  103. CLIENT WILL ASSUME THAT SOMETHING WENT WRONG AND IT WILL RETRANSMIT THE
  104. REQUEST.
  105.  
  106. ┴S POINTED OUT WAY ABOVE, THERE ARE TWO POSSIBLE REASONS FOR A RETRANSMISSION
  107. BEING NEEDED: EITHER THE REQUEST PACKET WAS CORRUPTED AND DROPPED, OR THE
  108. REPLY PACKET WAS CORRUPTED AND DROPPED.  ╔N THE FORMAT CASE, THE REQUEST
  109. WASN'T PROCESSED BY THE SERVER, BUT IN THE LATTER CASE, IT WAS.  ╙INCE WE
  110. DON'T WANT THE SERVER TO PERFORM AN FILE OPERATION TWICE (THIS IS REALLY
  111. WHAT THE SIX FILE-TRANSFER CLIENT OPERATIONS REALLY BOIL DOWN TO FROM THE
  112. SERVER'S PERSPECTIVE), THE SERVER MUST KEEP FOUR PIECES OF INTERNAL STATE:
  113. THE LAST UPLOAD SEQUENCE NUMBER, THE LAST DOWNLOAD SEQUENCE NUMBER, WHETHER
  114. THE UPLOAD FILE IS OPEN, AND WHETHER THE DOWNLOAD FILE IS OPEN.
  115.  
  116. ╔F AN UPLOAD-OPEN REQUEST IS RECEIVED AND THE FILE TO BE UPLOADED IS NOT OPEN,
  117. THE THE REQUEST MUST BE A NEW ONE AND THE SERVER PROCESSES IT AND SENDS BACK A
  118. REPLY LIKE NORMAL.  ╔F AN UPLOAD-OPEN REQUEST IS RECEIVE AND THE UPLOAD FILE
  119. ╔╙ CURRENTLY OPEN, THEN IT MUST BE THE CASE THAT THE CURRENT REQUEST IS A
  120. RETRANSMISSION, SO ALL THEAT THE SERVER NEEDS TO DO IS TO GIVE A POSITIVE
  121. REPLY WITHOUT PERFORMING ANY INTERNAL FILE OPERATIONS.  ╘HE SAME HOLDS TRUE
  122. FOR THE DOWNLOAD-OPEN CALL AND FOR BOTH OF THE CLOSE CALLS (EXCEPT THAT THE
  123. OPERATION HAS ALREADY BEEN PROCESSED IF THE FILE IS ├╠╧╙┼─).
  124.  
  125. ╞OR THE PACKET-UPLOAD AND PACKET-DOWNLOAD REQUESTS, SEQUENCE NUMBERS ARE USED
  126. TO DETECT DUPLICATES.  ┘OU WILL NOTE THAT THESE SEQUENCE NUMBERS ARE DISTINCT
  127. FROM ONE ANOTHER, AND, IN FACT, THAT THE ENTIRE UPLOAD AND DOWNLOAD FILE-
  128. TRANSFER CHANNELS ARE DISTINCT AND INDEPENDENT FROM EACH ANOTHER.  ╘HIS IS TO
  129. ALLOW FOR THE FUTURE POSSIBILITY OF SIMULTANEOUS FILE UPLOADING AND
  130. DOWNLOADING.  ╔N FACT, IF STREAM NUMBERS (FILE DESCRIPTORS) WERE ADDED TO THE
  131. OPEN/READ/WRITE/CLOSE REQUESTS, THEN WE COULD HAVE US A FULL-BLOWN REMOTE-HOST
  132. OVER-THE-PHONE INTERACTIVE FILE SERVER.  ┬UT ANYWHO, SEQUENCE NUMBERS START
  133. FROM 0X00 FOR THE FIRST PACKET TRANSFERRED AND INCREMENT MODULO 256 FROM
  134. THERE.
  135.  
  136. ╬OTE THAT FOR HIGH-SPEED DATA-COMPRESSION MODEMS (LIKE ╔ HAVE) THAT ALREADY
  137. INCLUDE ERROR DETECTION AND RECOVERY AT A LEVEL HIDDEN FROM THE USER, THE ╞╪
  138. PROTOCOL WILL WORK PARTICULARLY WELL: THERE WILL NEVER BE AN ERROR, NEVER BE A
  139. TIMEOUT DELAY, AND NEVER BE A RETRANSMISSION.  ┴ND, REALLY, THE ├╥├-32 ERROR
  140. COMPUTATION AND CHECKING IS PRETTY MUCH A ZERO COST.  ┬UT, IF SOMETHING DOES
  141. GO WRONG, OUTSIDE OF THE MODEM-TO-MODEM CONNECTION, THE ╞╪ PROTOCOL IS RIGHT
  142. THERE TO PICK UP THE PIECES AND CARRY ON.
  143.  
  144. 6. ├╧╬├╠╒╙╔╧╬
  145.  
  146. ┘OU'LL HAVE TO WAIT TO GET YOUR HANDS ON THE PROGRAM.  ╘HE ╒NIX ╙ERVER
  147. PROGRAM IS ALMOST 100% (EXCEPT FOR A FEW DESIGN CHANGES THAT ╔ MADE WHILE
  148. WRITING THIS DOCUMENT), AND THE ┴├┼ PROGRAM IS IMPLEMENTED EXCEPT FOR
  149. THE ERROR HANDLING AND TEXT CONVERSION.  ┬OTH PROGRAMS WILL BE RELEASED
  150. WITH THE NEXT RELEASE OF ┴├┼, WHICH WILL BE ╥EAL ╙OON ╬OW (╘═).
  151.  
  152. ╚ERE IS MY PERFORMANCE TESTING SO FAR, USING MY ╒╙╥ ╙PORTSTER MODEM OVER A
  153. 14.4-KBPS PHONE CONNECTION, WITH A 38.4-KBPS LINK TO MY MODEM FROM MY ├128, TO
  154. MY USUAL ╒NIX HOST:
  155.  
  156. ╒SING ╞╪ TO/FROM THE ┴├┼ RAMDISK, ╥┼╒:
  157.  
  158. ─OWNLOAD 156,260 BYTES OF ▐TEXT:        TIME= 54.1 SEC, RATE=2888 CPS.
  159. ─OWNLOAD 151,267 BYTES OF TABULAR TEXT: TIME= 45.9 SEC, RATE=3296 CPS.
  160. ─OWNLOAD 141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME= 92.5 SEC, RATE=1528 CPS.
  161. ╒PLOAD   156,260 BYTES OF ▐TEXT:        TIME= 57.4 SEC, RATE=2722 CPS.
  162. ╒PLOAD   151,267 BYTES OF TABULAR TEXT: TIME= 45.3 SEC, RATE=3339 CPS.
  163. ╒PLOAD   141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME= 95.0 SEC, RATE=1487 CPS.
  164.  
  165. ╒SING ╞╪ TO/FROM MY ├═─ ╚ARD ─RIVE:
  166.  
  167. ─OWNLOAD 156,260 BYTES OF ▐TEXT:        TIME= 83.4 SEC, RATE=1874 CPS.
  168. ─OWNLOAD 151,267 BYTES OF TABULAR TEXT: TIME= 75.4 SEC, RATE=2006 CPS.
  169. ─OWNLOAD 141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME=118.2 SEC, RATE=1195 CPS.
  170. ╒PLOAD   156,260 BYTES OF ▐TEXT:        TIME= 77.9 SEC, RATE=2006 CPS.
  171. ╒PLOAD   151,267 BYTES OF TABULAR TEXT: TIME= 66.2 SEC, RATE=2285 CPS.
  172. ╒PLOAD   141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME=114.2 SEC, RATE=1237 CPS.
  173.  
  174. ╒SING ─ES╘ERM-128 V2.00 TO/FROM MY ├═─ ╚ARD ─RIVE, ┘-═ODEM:
  175.  
  176. ─OWNLOAD 156,260 BYTES OF ▐TEXT:        TIME=189.5 SEC, RATE= 824 CPS.
  177. ─OWNLOAD 151,267 BYTES OF TABULAR TEXT: TIME=180.4 SEC, RATE= 839 CPS.
  178. ─OWNLOAD 141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME=199.9 SEC, RATE= 707 CPS.
  179. ╒PLOAD   156,260 BYTES OF ▐TEXT:        TIME=255.1 SEC, RATE= 611 CPS.
  180. ╒PLOAD   151,267 BYTES OF TABULAR TEXT: TIME=238.6 SEC, RATE= 634 CPS.
  181. ╒PLOAD   141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME=233.0 SEC, RATE= 606 CPS.
  182.  
  183. ╒SING ╬OVA╘ERM-64 V9.5 TO MY ├═─ ╚ARD ─RIVE, ┌-═ODEM, ├64 MODE:
  184.  
  185. ─OWNLOAD 156,260 BYTES OF ▐TEXT:        TIME=245.8 SEC, RATE= 636 CPS.
  186. ─OWNLOAD 151,267 BYTES OF TABULAR TEXT: TIME=230.0 SEC, RATE= 658 CPS.
  187. ─OWNLOAD 141,299 BYTES OF ╩╨┼╟ IMAGE:   TIME=262.6 SEC, RATE= 538 CPS.
  188.  
  189. (╘HERE IS NO ┌-═ODEM UPLOADING SUPPORT)
  190.  
  191. ╙O THERE YOU HAVE IT: MY SIMPLE PROTOCOL BLOWS THE OTHERS AWAY.  ╤┼─.
  192. ========================================================================
  193. ─┼╙╔╟╬ ┴╬─ ╔═╨╠┼═┼╬╘┴╘╔╧╬ ╧╞ ┴ '╥┼┴╠' ╧╨┼╥┴╘╔╬╟ ╙┘╙╘┼═ ╞╧╥ ╘╚┼ 128: ╨┴╥╘ ╔╔
  194.  
  195. BY ├RAIG ╙. ┬RUCE  <CSBRUCE@CCNGA.UWATERLOO.CA>
  196.  
  197. 0. ╨╥┼╞┴├┼
  198.  
  199. ╘HERE HAS BEEN A SLIGHT CHANGE IN PLANS.  ╔ ORIGINALLY INTENDED THIS ARTICLE
  200. TO GIVE THE DESIGN OF A THEORETICAL DISTRIBUTED MULTITASKING MICROKERNEL
  201. OPERATING SYSTEM FOR THE ├128.  ╔ HAVE DECIDED TO GO A DIFFERENT ROUTE: TO
  202. TAKE OUT THE DISTRIBUTED COMPONENT FOR NOW AND IMPLEMENT A REAL MULTITASKING
  203. MICROKERNEL ╧╙ FOR A SINGLE MACHINE AND EXTEND THE SYSTEM TO BE DISTRIBUTED
  204. LATER.  ╘HE IMPLEMENTATION SO FAR IS, OF COURSE, ONLY IN THE PROTOTYPE STAGE
  205. AND THE APPLICATION FOR IT IS ONLY A DEMO.  ╨ART ╔╔╔ OF THIS SERIES WILL
  206. EXTEND THIS DEMO SYSTEM INTO, PERHAPS, A USABLE DISTRIBUTED OPERATING SYSTEM.
  207.  
  208. 1. ╔╬╘╥╧─╒├╘╔╧╬
  209.  
  210. ╘HE PREVIOUS ARTICLE TALKED ABOUT THE GENERAL APPROACH TO BUILDING A
  211. MULTITASKING MICROKERNEL ╧╙ FOR THE ├128.  ╔T IS ASSUMED HERE THAT YOU HAVE
  212. READ AND UNDERSTOOD THE PREVIOUS ARTICLE.  ╘HIS ARTICLE GOES INTO THE GRUNGY
  213. DETAILS OF IMPLEMENTING SUCH A BEAST.  ╘HE PROTOTYPE KERNEL IMPLEMENTATION
  214. PROVIDES SYSTEM CALLS TO CREATE AND "EXIT" USER PROCESSES, OBTAIN STATUS
  215. INFORMATION, DELAY EXECUTION OF A PROCESS FOR A SPECIFIED PERIOD OF TIME,
  216. AND TO PERFORM MESSAGE-PASSING INTERPROCESS COMMUNICATION.
  217.  
  218. ├URRENTLY, THERE IS NO REAL MEMORY MANAGEMENT, NO REAL DEVICE DRIVERS, AND NO
  219. PROCESS-RESOURCE RECLAMATION.  ═ORE "INFRASTRUCTURE" FEATURES NEED TO BE ADDED
  220. BEFORE A COMMAND-SHELL ENVIRONMENT OR ANY SUCH THING COULD BE SUPPORTED,
  221. THOUGH NOT TOOOO MANY MORE; THE ├OMMODORE-╦ERNAL ╙ERVER IN THE DEMO SYSTEM
  222. MAKES THE $╞╞─2 (├╚╥╧╒╘) ROUTINE OF THE ├OMMODORE ╦ERNAL AVAILABLE TO ALL
  223. OTHER PROCESSES IN THE DEMO SYSTEM.  ╔T COULD EASILY BE MODIFIED TO PROVIDE
  224. ALL OF THE ├OMMODORE-╦ERNAL FEATURES TO THE OTHER PROCESSES, THEREBY GIVING
  225. US A BASIC ╔/╧ SUB-SYSTEM.
  226.  
  227. ╘HERE IS ALSO NO WAY TO DYNAMICALLY LOAD EXTERNAL PROGRAMS, SO THE TEST
  228. PROGRAMS HAVE TO BE ASSEMBLED WITH THE KERNEL CODE.  ╠OADING EXTERNAL PROGRAMS
  229. IN THIS TYPE OF ENVIRONMENT HAS THE REQUIREMENT THAT THE PROGRAM WILL HAVE TO
  230. BE RELOCATED UPON BEING LOADED TO AN ADDRESS THAT WOULD ONLY BE KNOWN AT LOAD
  231. TIME.  ╘HERE ARE TWO WAYS TO GO ON THIS: LOAD ALL PROGRAMS TO A FIXED ADDRESS
  232. OR LOAD THEM TO DYNAMIC ADDRESSES.  ╔F YOU LOAD THEM TO A FIXED ADDRESS, THEN
  233. YOU CAN ONLY HAVE ONE PROCESSES LOADED AND CONCURRENTLY RUNNING ON EACH BANK
  234. OF INTERNAL MEMORY OF THE ├128 AND THEN DEMAND-SWAP ALL OF THE OTHER PROCESSES
  235. INTO AND OUT OF THESE (TWO) SLOTS, PRESUMABLY FROM ╥┼╒ MEMORY (ANY OTHER TYPE
  236. WOULD BE MUCH TOO SLOW).  ╔╚═╧, EVEN WITH ╥┼╒ MEMORY, THIS WOULD BE TOO SLOW,
  237. ESPECIALLY FOR A MICROKERNEL ENVIRONMENT.  ╙O, PROGRAMS WILL NEED TO BE
  238. LOADED TO DYNAMIC ADDRESSES.  ╞ORTUNATELY, ╔ HAVE A PROGRAM-RELOCATION
  239. MECHANISM IN THE WORKS.
  240.  
  241. ╘HE ENTIRE KERNEL AND THE DEMO PROGRAM FITS IN ├128 MEMORY IN THE SLOT BETWEEN
  242. $1300 AND $1┬╞╞ OF ╥┴═0.  ╘HE KERNEL USES STORAGE FROM $├00-$├╞╞ AND
  243. $2000-$┬╞╞╞.  ╘HE LATTER SECTION OF MEMORY IS USED UP IN 768-BYTE CHUNKS BY
  244. EACH NEW PROCESS, SO THERE CAN BE A TOTAL OF 53 CONCURRENTLY EXECUTING USER
  245. PROCESSES IN THE SYSTEM.
  246.  
  247. 2. ╘┼╙╘ ╨╥╧╟╥┴═
  248.  
  249. ╘HE TEST PROGRAM INCLUDES NO PROVISIONS FOR USER INTERACTION, SO IT MAY NOT
  250. BE SOMETHING THAT YOU CAN IMPRESS YOUR FRIENDS WITH, BUT ╔ CAN ASSURE YOU
  251. THAT ALL KINDS MULTITASKING STUFF IS GOING ON BEHIND THE SCENES TO MAKE
  252. EVERYTHING HAPPEN.
  253.  
  254. ╘HE DEMO TEST PROGRAM CREATES TEN PROCESSES.  ╘HERE ARE FIVE "DELAY"
  255. PROCESSES, TWO "BLABBERING" PROCESSES, A ├OMMODORE-╦ERNAL-╙ERVER PROCESS, ONE
  256. ╙╔─-BANGING PROCESS, AND THE ╬ULL PROCESS.  (╬OTE THAT WHEN ╔ USE THE WORD
  257. "KERNEL" ╔ AM REFERRING TO THE ╧╙ THAT ╔ HAVE WRITTEN, AND WHEN ╔ USE THE WORD
  258. "╦ERNAL", ╔ AM REFERRING TO THE ├OMMODORE ╦ERNAL IN ╥╧═).
  259.  
  260. ╘HE PURPOSE OF THE ├OMMODORE-╦ERNAL ╙ERVER IS TO RECEIVE REQUESTS FROM THE
  261. WORKER PROCESSES TO CALL THE ├╚╥╧╒╘ ROUTINE TO PRINT A GIVEN LINE OF TEXT OUT
  262. TO THE SCREEN.  ╘HE ╦ERNAL SERVER IS THE ONLY PROCESSES THAT IS ALLOWED TO
  263. CALL THE ├OMMODORE-╦ERNAL ROUTINES.  ╙INCE IT CAN ONLY PROCESS ONE REQUEST
  264. FROM A CLIENT PROCESS AT A TIME, CALLS TO THE ├OMMODORE ╦ERNAL ARE EFFECTIVELY
  265. "SERIALIZED" (MADE TO HAPPEN ONE AFTER ANOTHER IN TIME), WHICH IS GOOD, SINCE
  266. THINGS WOULD BLOW UP PRETTY BADLY IF TWO ACCESSES THE ├OMMODORE ╦ERNAL WERE TO
  267. HAPPEN CONCURRENTLY.
  268.  
  269. ╘HE "DELAY" PROCESSES, NUMBERED FROM 1 TO 5, EACH DELAY FOR A PERIOD OF ╬
  270. SECONDS AND THEN REQUEST THE ╦ERNAL ╙ERVER TO PRINT A "╔'M ALIVE" MESSAGE TO
  271. THE SCREEN.  ╘HE NUMBER ╬ OF SECONDS TO DELAY IS THE NUMBER OF THE PROCESS.
  272. ┘OU SHOULD BE ABLE TO OBSERVE FROM WATCHING THE EXECUTION THAT EACH DELAY
  273. PROCESS PRINTS A MESSAGE TO THE SCREEN WITH APPROXIMATELY THE CORRECT PERIOD
  274. BETWEEN MESSAGES.  ╬OTE THAT WHILE THESE PROCESSES ARE DELAYING, THEY DON'T
  275. USE ANY ├╨╒ TIME, SO THE ├╨╒ TIME IS ALLOCATED TO OTHER PROCESSES.  ╔F YOU
  276. TRY HOLDING DOWN THE ├= KEY TO SLOW THE SCROLLING OR RUN THE SYSTEM IN ╙LOW
  277. MODE, YOU WILL STILL NOTICE THAT THE DELAY PROCESSES GENERATE THEIR OUTPUT
  278. AT APPROXIMATELY THE RIGHT TIME.
  279.  
  280. ╘HE TWO "BLABBERING" PROCESSES, NAMED "BLABBER" AND "SPINNER", CONTINUALLY
  281. SEND PRINT MESSAGES TO THE ├OMMODORE-╙ERVER PROCESS.  ┘OU WILL OBSERVE THAT
  282. THE MESSAGES FROM EACH COMES PRETTY MUCH PREFECTLY INTERLEAVED WITH EACH
  283. OTHER, AND WITH THE OUTPUT OF THE DELAY PROCESS, BECAUSE OF THE INTERPROCESS
  284. COMMUNICATION SCHEDULING POLICY: ╞╔╞╧ (FIRST-IN, FIRST-OUT).
  285.  
  286. ╘HE ╙╔─-BANGING PROCESS RUNS CONTINUOUSLY IN THE BACKGROUND.  ╔T INCREMENTS
  287. THE 16-BIT FREQUENCY OF VOICE #1 FROM $0000 TO $FFFF AND THEN SUSPENDS ITS
  288. EXECUTION FOR TWO SECONDS AND THEN REPEATS.  ┴ SQUARE WAVE WITH EVEN PULSE
  289. WIDTHS IS USED.  ╫HEN THE ╙╔─ PROCESS DELAYS FOR TWO SECONDS, YOU WILL NOTICE
  290. THAT THE PRINTING OPERATION OF THE OTHER PROCESSES SPEEDS UP A BIT.  ╘HIS IS
  291. BECAUSE THE ╙╔─ PROCESS IS A HEAVY ├╨╒ USER WHILE IT IS ACTIVE.  ╘HE AMOUNT OF
  292. SLOW-DOWN OF THE REST OF THE SYSTEM IS LIMITED A BIT BECAUSE THE ╙╔─ PROCESS
  293. RUNS WITH A SLIGHTLY LOWER PRIORITY THAN THE OTHER PROCESSES IN THE SYSTEM
  294. (WHICH MAKES THE SOUND INCREMENT SLIGHTLY SLOWER THAN IT OTHERWISE WOULD --
  295. THERE'S ONLY SO MUCH ├╨╒ TO GO AROUND).
  296.  
  297. ╘HE ╬ULL PROCESS IS NOT ACTUALLY NEEDED IN THIS EXERCISE, BUT IT WOULD
  298. NORMALLY BE USED TO INSURE THAT THE SYSTEM ALWAYS HAD SOME PROCESS TO
  299. SCHEDULE.  ┴LL THAT IT DOES IS INCREMENT THE BINARY VALUE IN LOCATIONS
  300. $0400-$0403 (ON THE 40-COLUMN SCREEN) WHENEVER IT IS ACTIVE.  ╔T HAS THE
  301. LOWEST PRIORITY IN THE SYSTEM AND NEVER GETS TO EXECUTE UNLESS ALL OF THE
  302. OTHER PROCESSES ARE BLOCKED (I.E., ARE SUSPENDED FOR SOME REASON).
  303.  
  304. ╫HEN YOU GET TIRED OF WATCHING THE DEMO, YOU CAN JUST HIT THE ╥┼╙╘╧╥┼ KEY.
  305. ╘HIS WILL CAUSE AN ╬═╔ WHICH WILL MAKE THE SYSTEM EXIT BACK TO ┬┴╙╔├.  ╘HE
  306. SYSTEM DOES NOT HAVE THE ABILITY TO HANDLE EXTERNAL EVENTS (LIKE KEY STROKES)
  307. AT THIS TIME.  ┴ COUPLE OF LOCATIONS ON THE 40-COLUMN SCREEN ARE USED FOR
  308. STATUS INFORMATION, SO YOU WILL WANT TO RUN THE DEMO ON THE 80-COLUMN SCREEN.
  309.  
  310. 3. ╨╥╧├┼╙╙ ├╧╬╘╥╧╠
  311.  
  312. ┴ PROCESS IS A USER PROGRAM THAT IS IN AN ACTIVE STATE OF EXECUTION.  ┴
  313. PROCESS IS PERIODICALLY GIVEN A CERTAIN AMOUNT OF ├╨╒ TIME TO EXECUTE ITS
  314. CODE, AND THEN ├╨╒ ATTENTION IS TAKEN AWAY FROM IT TO EXECUTE OTHER
  315. PROCESSES.  ╘HIS MAY SOUND LIKE YOU'RE SIMPLY MAKING ╬ PROCESSES RUN ╬ TIMES
  316. SLOWER, AND THIS IS TRUE IN THE WORST CASE, BUT THE NORMAL CASE IS THAT MANY
  317. PROCESSES IN THE SYSTEM WILL BE BLOCKED (FOR WHATEVER REASON) AND WILL NOT
  318. REQUIRE ANY MORE ├╨╒ TIME UNTIL THEY WAKE UP AGAIN (FOR WHATEVER REASON).
  319. ╘HEREFORE, MULTITASKING IS A "WINNABLE" PROPOSITION.
  320.  
  321. ╔N OUR SYSTEM, THE PROCESS THAT THE ├╨╒ IS CURRENTLY EXECUTING IS CHANGED
  322. EVERY 1/60 OF A SECOND.  ╘HIS IS A CONVENIENT "QUANTUM" PERIOD FOR A NUMBER OF
  323. REASONS, INCLUDING THE FACT THAT, THANKS TO THE ══╒ OF THE ├128, "CONTEXT
  324. SWITCHING" CAN BE EFFICIENTLY PERFORMED THIS QUICKLY.
  325.  
  326. 3.1. ╨╥╧├┼╙╙-├╧╬╘╥╧╠ ├┴╠╠╙
  327.  
  328. ╘HERE ARE SIX KERNEL CALLS THAT DEAL WITH PROCESS CONTROL:
  329.  
  330. ├┴╠╠ ╬┴═┼     ╔╬╨╒╘ ┴╥╟╒═┼╬╘╙                  ╥┼╘╒╥╬ ╓┴╠╒┼╙
  331. -----------   ------------------------------   -------------------------------
  332. ├REATE        ( .┴┘=ADDRESS, .╪=PRIORITY )     .┴┘=NEW╨ID, .├╙=ERR(.┴=ERRCODE)
  333. ┼XIT          ( .┴=CODE, .╪=$00 )              <NONE>
  334. ═Y╨ID         ( )                              .┴┘=PID
  335. ═Y╨ARENT╨ID   ( )                              .┴┘=PARENT╨ID
  336. ╙USPEND       ( )                              <NONE>
  337. ─ELAY         ( .┴┘=JIFFIES )                  <NONE>
  338.  
  339. 3.1.1. ├╥┼┴╘┼
  340.  
  341. ╘HE ├REATE() KERNEL CALL IS USED TO CREATE A NEW PROCESS.  ╘HE FIRST INPUT
  342. ARGUMENT IS THE CODE ADDRESS, AND IT IS PASSED IN THE .┴┘ REGISTER (.┴ IS
  343. LOADED WITH THE LOW BYTE OF THE ADDRESS, AND THE .┘ REGISTER IS LOADED WITH
  344. THE HIGH BYTE OF THE ADDRESS--.┴┘ FOR SHORT).  ╘HE CODE MUST BE PRESENT IN
  345. MEMORY AND BE READY TO BE EXECUTED, SINCE THERE IS NO FACILITY FOR LOADING
  346. EXTERNAL PROGRAMS.  ┴LSO, IF THE CODE IS NOT RE-ENTRANT, THEN THERE MUST BE NO
  347. OTHER PROCESS ALREADY EXECUTING IT OR THINGS WILL LIKELY BLOW UP.  ╥E-ENTRANT
  348. CODE IS CODE THAT CAN BE EXECUTED BY MULTIPLE PROCESSES SIMULTANEOUSLY WITHOUT
  349. CONFLICTS, ESSENTIALLY BECAUSE THERE ARE NO GLOBAL VARIABLES THAT COULD BE
  350. BANGED ON BY MORE THAN ONE PROCESS AT A TIME.
  351.  
  352. ╘HE PRIORITY ARGUMENT IS THE PRIORITY TO EXECUTE THE NEW PROCESS AT.  ╓ALID
  353. VALUES FOR THIS ARGUMENT ARE ON THE RANGE 0 TO 127.  ╘HE SYSTEM KEEPS A LIST
  354. AT ALL TIMES OF ALL THE PROCESSES THAT ARE READY TO EXECUTE, CALLED THE "READY
  355. LIST".  ╘HE WAY THAT THE SCHEDULING WORKS IS THAT A POINTER TO THE "ACTIVE"
  356. PROCESS IS KEPT (THE ONE THAT IS CURRENTLY EXECUTING) AND THIS POINTER CYCLES
  357. THROUGH THE READY LIST, TRYING TO ACTIVATE EACH PROCESS IN TURN, EVERY 1/60 OF
  358. A SECOND.  ╘HIS IS ROUNDROBIN SCHEDULING.  ╘HE PRIORITY OF A PROCESS
  359. DETERMINES THE NUMBER OF CYCLES THAT THE ACTIVE-PROCESS POINTER HAS TO TAKE
  360. THROUGH THE LIST BEFORE THE PROCESS IS ACTIVATED.  ╙O, IF A PROCESS HAS
  361. PRIORITY 1, THEN IT WILL BE ACTIVATED ON EVERY ROUND; IF IT HAS A PRIORITY OF
  362. 2, THEN IT WILL BE ACTIVATED ON EVERY SECOND ROUND; AND IF IT HAS A PRIORITY
  363. OF 86, THEN IT WILL BE ACTIVATED ONLY ON EVERY 86TH ROUND THROUGH THE READY
  364. LIST.  ╘HE HIGHER THE PRIORITY VALUE, THE SLOWER THE PROCESS EXECUTES.  ╘HIS
  365. POLICY GIVES A FAIR ALLOCATION OF THE ├╨╒ TO THE VARIOUS PROCESSES IN THE
  366. SYSTEM.
  367.  
  368. ╬ORMALLY, FOREGROUND PROCESSES (ONES THAT PERFORM ACTIONS RIGHT IN FRONT OF
  369. THE USER'S FACE) SHOULD HAVE A PRIORITY OF 1, AND BACKGROUND PROCESSES SHOULD
  370. HAVE A RELATIVELY LOWER PRIORITY.  ┴ PRIORITY VALUE OF 0 FOR A PROCESS MEANS
  371. THAT WHEN THE PROCESS IS ACTIVATED, IT WILL NOT BE DEACTIVATED AGAIN UNTIL IT
  372. BLOCKS FOR SOME REASON.  ╘HIS PRIORITY LEVEL SHOULD BE RESERVED FOR URGENT
  373. COMPUTATIONS THAT BLOCK OFTEN, SINCE IT HAS THE POTENTIAL TO STARVE OUT THE
  374. REST OF THE SYSTEM.  ╘HE ╬ULL PROCESS EXECUTES AT A SPECIAL PRIORITY LEVEL
  375. (255) THAT MAKES IT SO THAT IT WILL ONLY BE ACTIVATED IF THERE ARE NO OTHER
  376. PROCESSES IN THE READY LIST.
  377.  
  378. ╘HE ├REATE() CALL RETURNS WITH THE CARRY FLAG CLEAR AND THE PROCESS ID OF THE
  379. NEWLY CREATED PROCESS IN THE .┴┘ REGISTER UPON SUCCESS, OR RETURNS WITH THE
  380. CARRY FLAG SET AND AN ERROR CODE IN THE .┴ REGISTER UPON FAILURE.  ╔ DO NOT
  381. HAVE THE COMPLETE LIST OF ERROR CONDITIONS FIGURED OUT A THIS TIME, BUT ERRORS
  382. WILL USUALLY HAPPEN ON A CALL LIKE THIS BECAUSE OF A LACK OF RESOURCES
  383. (MEMORY) FOR THE KERNEL'S INTERNAL DATA STRUCTURES.  ╒PON SUCCESSFUL RETURN,
  384. THE CHILD PROCESS IS CREATED, MADE READY, AND MAY BE ACTIVATED BY THE SYSTEM
  385. AT ANY TIME.  ╘HE FIRST INSTRUCTION TO BE EXECUTED BY THE CHILD WILL BE AT THE
  386. VALUE GIVEN FOR THE CODE ADDRESS.
  387.  
  388. ╘HE NEWLY CREATED PROCESS WILL HAVE A CLEAR INDIVIDUAL STACK, EXCEPT FOR A
  389. COUPLE OF BYTES ON THE VERY BOTTOM OF IT (HIGH ADDRESSES), AND A CLEAR
  390. INDIVIDUAL ZEROPAGE.  ╨ROCESSES ARE ALLOWED TO MAKE FULL USE OF EVERY LOCATION
  391. IN THEIR ZEROPAGE, EXCEPT FOR THE ╔/╧ REGISTERS AT LOCATIONS 0 AND 1, AND FULL
  392. USE OF THEIR STACK, EXCEPT THAT THEY MUST MAKE SURE THAT ABOUT A DOZEN BYTES
  393. ARE AVAILABLE ON THE STACK AT ALL TIMES IN CASE AN INTERRUPT HAPPENS.
  394.  
  395. 3.1.2. ┼╪╔╘
  396.  
  397. ╘HE ┼XIT() KERNEL CALL IS USED TO REMOVE THE CURRENT PROCESS FROM THE SYSTEM.
  398. ╘HERE ARE TWO INPUT ARGUMENTS: THE .┴ REGISTER CONTAINS THE RETURN CODE THAT
  399. WILL BE MADE AVAILABLE TO THE PARENT PROCESS IF IT IS INTERESTED (THOUGH NOT
  400. IN THE CURRENT IMPLEMENTATION), AND A VALUE IN THE .╪ REGISTER, WHICH MUST
  401. CURRENTLY BE $00.  ╔ HAVEN'T FIGURED OUT EXACTLY HOW THE EXIT MECHANISM SHOULD
  402. WORK YET AND IT CURRENTLY ONLY HAS A MINIMAL IMPLEMENTATION.  ╘HE CALL DOES
  403. MAKE THE KERNEL RECLAIM THE RESOURCES THAT WERE ALLOCATED TO THE PROCESS YET,
  404. ALTHOUGH THIS FUNCTIONALITY WILL BE NEEDED IN ANY REAL OPERATING SYSTEM.
  405.  
  406. ╘HERE IS NO RETURN VALUE FROM THE ┼XIT() CALL, BECAUSE THE CALL NEVER RETURNS.
  407. ╘HE SEMANTICS OF THE CALL IS THE THE PROCESS CALLING ┼XIT() WILL NEVER BE MADE
  408. ACTIVE AGAIN.  ┴LL PROCESSES SHOULD CALL ┼XIT() WHEN THEY ARE FINISHED
  409. EXECUTING, OR THEY CAN ACHIEVE THE SAME RESULT BY EXECUTING AN ╥╘╙ INSTRUCTION
  410. AT THE END OF THEIR MAIN ROUTINE.  ╘HE KERNEL PUSHES THE ADDRESS OF AN ┼XIT()
  411. STUB ROUTINE ONTO THE TOP OF THE STACK OF A USER PROCESS WHEN IT IS CREATED,
  412. AND THE USER PROCESS WILL EXIT WITH A RETURN CODE OF $00 IN THIS CASE.
  413.  
  414. 3.1.3. ═┘_╨╔─
  415.  
  416. ╘HE ═Y╨ID() KERNEL CALL IS USED TO RETURN THE PROCESS IDENTIFIER OF THE
  417. CURRENT PROCESS.  ╘HIS CALL IS VERY SIMPLE, TAKES NO ARGUMENTS, AND EXECUTES
  418. VERY QUICKLY.  ╘HE RETURN VALUE IS THE PROCESS ID OF THE CALLING PROCESS AND
  419. IS RETURNED IN THE .┴┘ REGISTER.  ╘HIS CALL CANNOT FAIL, BECAUSE THE CURRENT
  420. PROCESS MUST EXIST IN ORDER TO MAKE THE CALL IN THE FIRST PLACE, SO THERE IS
  421. NO ERROR-RETURN CONDITION.
  422.  
  423. 3.1.4. ═┘_╨┴╥┼╬╘_╨╔─
  424.  
  425. ╘HE ═Y╨ARENT╨ID() KERNEL CALL IS USED TO RETURN THE PROCESS IDENTIFIER OF THE
  426. PARENT PROCESS OF THE CURRENT PROCESS (I.E., THE PROCESS THAT CREATED THE
  427. CURRENT PROCESS).  ╘HIS CALL IS SIMPLE, TAKES NO ARGUMENTS, AND EXECUTES
  428. QUICKLY, VERY MUCH LIKE THE ═Y╨ID() CALL.  ╬O ERROR RETURNS ARE POSSIBLE, AND
  429. THE PROCESS ID OF THE PARENT TO THE CURRENT PROCESS IS RETURNED IN THE .┴┘
  430. REGISTER.  ┬UT NOTE: IT IS NOT GUARANTEED THAT THE PARENT PROCESS WILL STILL
  431. EXIST EITHER BEFORE OR AFTER THE CURRENT PROCESS MAKES THIS CALL; IT MAY HAVE
  432. ┼XIT()ED.  ╔ MAY RE-THINK THIS SEMANTIC.
  433.  
  434. ╘HIS CALL IS USEFUL FOR SETTING UP INTERPROCESS COMMUNICATION BETWEEN A CHILD
  435. PROCESS AND ITS PARENT.
  436.  
  437. 3.1.5. ╙╒╙╨┼╬─
  438.  
  439. ╘HE ╙USPEND() KERNEL CALL IS USED TO SUSPEND THE EXECUTION OF THE CURRENTLY
  440. EXECUTING PROCESS FOR AN INDEFINITE PERIOD OF TIME.  ├URRENTLY, THIS PERIOD OF
  441. TIME IS FOREVER, SINCE THERE IS NO CORRESPONDING "╥ESUME" SYSTEM CALL THAT
  442. ANOTHER PROCESS CAN CALL IN ORDER TO WAKE UP THE PROCESS THAT SUSPENDED
  443. ITSELF.  ╘HE REASON THAT THIS CALL IS MADE AVAILABLE IS BECAUSE THE GUTS OF
  444. WHAT IT DOES IS REQUIRED BY OTHER KERNEL OPERATIONS, AND THE COST OF MAKING
  445. THIS CALL USER-ACCESSIBLE WAS THREE 6502 INSTRUCTIONS.  ╘HIS CALL MAY BE
  446. RETRACTED IN THE FUTURE, SINCE IT MAY CAUSE PROGRAMMERS TO DO BAD THINGS.
  447.  
  448. ╘HE CALL TAKES NO ARGUMENTS, RETURNS NO VALUES, AND CURRENTLY, WILL NEVER
  449. RETURN AT ALL, MUCH LIKE ┼XIT().
  450.  
  451. 3.1.6. ─┼╠┴┘
  452.  
  453. ╘HE ─ELAY() KERNEL CALL IS USED TO SUSPEND THE EXECUTION OF THE CURRENT
  454. PROCESS FOR A USER-SPECIFIED PERIOD OF TIME.  ╘HE DELAY PERIOD IS GIVEN IN
  455. UNITS OF JIFFIES (1/60THS OF A SECOND).  ╘HE UNSIGNED 16-BIT DELAY PERIOD IS
  456. PASSED IN IN THE .┴┘ REGISTERS, GIVING A MAXIMUM POSSIBLE DELAY PERIOD OF
  457. ABOUT 18 MINUTES.  ╔F A USER PROCESS REQUESTS TO DELAY FOR A PERIOD OF ZERO
  458. JIFFIES, ITS EXECUTION WILL NOT BE SUSPENDED AT ALL AND THE ─ELAY() PRIMITIVE
  459. WILL RETURN IMMEDIATELY.
  460.  
  461. ╙INCE THERE MAY BE OTHER PROCESSES IN THE SYSTEM DOING THINGS WHEN THE CURRENT
  462. PROCESSES WAKES UP AFTER DOING A DELAY, YOU CAN THINK OF THE PROCESS DELAYING
  463. FOR "AT LEAST" THE PERIOD OF TIME THAT YOU SPECIFY.  ┴CTUALLY, TO MUDDY THINGS
  464. EVEN MORE, YOUR PROCESS WILL ALWAYS GO TO SLEEP AT A MOMENT IN TIME THAT IS
  465. INBETWEEN TWO TICKS OF THE JIFFY CLOCK, SO THE FIRST "JIFFY" THAT YOUR PROCESS
  466. WAITS MAY ACTUALLY BE ANY PERIOD BETWEEN A COUPLE OF MICROSECONDS TO ALMOST A
  467. FULL JIFFY, WITH A STATISTICAL AVERAGE OF HALF A JIFFY.  ╘HIS IS AN ARTIFACT
  468. OF ANY COARSE-TICK-BASED MECHANISM.
  469.  
  470. ╘O MUDDY THINGS AGAIN, THE JIFFY TICKS, WHICH ARE CURRENTLY BASED ON ╓╔├
  471. RASTER INTERRUPTS (ONE PER SCREEN UPDATE), MAY NOT BE PROCESSED IMMEDIATELY
  472. WHEN THEY OCCUR, SINCE THE ╔╥╤ MAY BE DELAYED BY A SMALL PERIOD OF TIME IF
  473. INTERRUPTS ARE DISABLED IN THE PROCESSOR STATUS REGISTER WHEN THE JIFFY TICK
  474. HAPPENS.  ┴ND FINALLY, YOU SHOULD NOTE THAT YOU WILL HAVE A DIFFICULT TIME
  475. USING THIS CALL FOR TRUE "REAL TIME" PERIODIC OPERATIONS, LIKE PERFORMING SOME
  476. SPECIFIC TASK PRECISELY EVERY TENTH OF A SECOND, SINCE THE CALL SPECIFIES A
  477. PERIOD TO DELAY FOR, RATHER THAN A TIME TO WAKE UP AT.  ╘HE ACTUAL PERIOD OF
  478. YOUR PROCESS' ACTIVATIONS WILL BE DETERMINED BY THE WAITING TIME PLUS THE TIME
  479. SKEW CAUSED BY THE PROCESSING THAT YOUR PROCESS DOES.  ┴ ─ELAY╒NTIL() CALL
  480. EASILY COULD BE IMPLEMENTED, IF ╔ FIGURE THAT IT WILL BE NEEDED FOR ANYTHING.
  481.  
  482. ├URRENTLY, THE SCHEDULING POLICY IS TO MAKE PROCESSES ACTIVE IMMEDIATELY AFTER
  483. THEY ARE AWAKENED, SO THIS MAKES THE ACTIVITIES OF OTHER PROCESSES LESS OF A
  484. WORRY TO ACCURATE TIMING.  ╒NIX DOES A SIMILAR THING BY GIVING A FRESHLY
  485. AWAKENED PROCESS A TEMPORARILY HIGH PRIORITY, SINCE IT IS PROBABLY LIKELY THAT
  486. THE PROCESS WILL DO SOME SMALL THINK AND THEN BLOCK AGAIN.  ╘HIS POLICY
  487. STATISTICALLY IMPROVES CONCURRENCY.
  488.  
  489. 3.2. ╨╥╧├┼╙╙ ├╧╬╘╥╧╠ ┬╠╧├╦╙
  490.  
  491. ┴ ╨ROCESS ├ONTROL ┬LOCK (╨├┬) IS THE DATA STRUCTURE THAT THE KERNEL KEEPS THE
  492. INFORMATION THAT IT NEEDS TO KNOW ABOUT A PROCESS IN.  ┴ ╨ROCESS IDENTIFIER
  493. (PID) IS ACTUALLY THE ╥┴═0 ADDRESS OF THE PROCESS CONTROL BLOCK OF A PROCESS,
  494. FOR CONVENIENCE, THOUGH THIS WILL HAVE TO CHANGE LATER.  ╘HE FIELDS OF THE
  495. PROCESS CONTROL BLOCK ARE SHOWN HERE, ORGANIZED INTO CLASSES:
  496.  
  497. ╧╞╞   ╙╔┌   ├╠┴╙╙   ╠┴┬┼╠
  498. ---   ---   -----   ------
  499.   0     2   QUEUE   PCB╬EXT
  500.   2     2   QUEUE   PCB╨REV
  501.   4     1   QUEUE   PCB╔S╚EAD
  502.   5     1   QUEUE   PCB╤├OUNT
  503.   6     1   CTXT    PCB╙╨
  504.   7     1   CTXT    PCB╙TACK╨AGE
  505.   8     1   CTXT    PCB┌ERO╨AGE
  506.   9     1   CTXT    PCB─506
  507.  10     1   SCHED   PCB╨RIORITY
  508.  11     1   SCHED   PCB├OUNTDOWN
  509.  12     2   SCHED   PCB╫AKEUP╘IME
  510.  12     2   IPC     PCB╙END═SG╨TR  (OVERLAP)
  511.  12     2   IPC     PCB╥ECV═SG╨TR  (OVERLAP)
  512.  14     2   IPC/Q   PCB╙END╤╚EAD
  513.  16     2   IPC/Q   PCB╙END╤╘AIL
  514.  18     1   IPC/Q   PCB╙END╤╞LAG
  515.  19     1   IPC/Q   PCB╙END╤├OUNT
  516.  20     2   IPC     PCB┬LOCKED╧N
  517.  22     2   IPC     PCB╥ECEIVE╞ROM
  518.  24     2   PROC    PCB╨ARENT
  519.  26     1   PROC    PCB╙TATE
  520.  27     -   -       ╙╔┌┼
  521.  
  522. 3.2.1. ╤╒┼╒┼-├╠┴╙╙ ╞╔┼╠─╙
  523.  
  524. ╘HE FIRST FOUR FIELDS, OF THE CLASS "QUEUE" ARE USED FOR MAINTAINING A PROCESS
  525. CONTROL BLOCK IN QUEUES WITH OTHER ╨├┬S.  ╙OME GENERAL-PURPOSE QUEUE-HANDLING
  526. ROUTINES HAVE BEEN WRITTEN TO MAKE QUEUE MANAGEMENT EASIER:  ╤UEUE╔NIT(),
  527. ╤UEUE╔NSERT(), AND ╤UEUE╒NLINK().  ┼ACH QUEUE HAS A HEAD NODE, AND THE NODES
  528. IN A DOUBLY LINKED CIRCULAR ORDER.  ╘HIS MEANS THAT EACH NODE IN THE QUEUE HAS
  529. A FORWARD ("PCB╬EXT") AND A BACKWARD ("PCB╨REV") POINTER AND THAT THE FIRST
  530. NODE POINTS BACK TO THE HEAD AND THE LAST NODE IN A LIST POINTS FORWARD TO THE
  531. HEAD.  ╘HIS ORGANIZATION REMOVES ALL OF THE QUIRKS OF HANDLING NULL POINTERS
  532. FROM THE CODE.  ╒SING A DOUBLY LINKED ORGANIZATION MAKES IT EASY TO REMOVE AN
  533. ARBITRARY NODE FROM THE MIDDLE OF A QUEUE.
  534.  
  535. ┼ACH NODE ALSO HAS A "PCB╔S╚EAD" FIELD WHICH IS ALWAYS ╞ALSE (ZERO) AND A
  536. "PCB╤├OUNT" FIELD WHICH IS ALWAYS ZERO.  ╘HE HEAD IS THE SAME AS AN ENTRY IN
  537. THE QUEUE, EXCEPT THAT ITS "PCB╔S╚EAD" FIELD IS SET TO ╘RUE ($FF) AND ITS
  538. "PCB╤├OUNT" FIELD RECORDS THE NUMBER OF NODES THAT ARE IN THE QUEUE AT ANY
  539. TIME.  ╘HE "PCB╔S╚EAD" FIELD IS CHECKED WHEN SCANNING A LIST TO TELL IF YOU'VE
  540. BUMPED BACK INTO THE HEAD NODE AGAIN, INDICATING THE END OF THE LIST.  ╘HE
  541. "PCB╤├OUNT" FIELD IS VERY CONVENIENT TO CHECK TO SEE WHETHER THE QUEUE IS
  542. EMPTY OR NOT.
  543.  
  544. ┴LL OF THE PROCESSES THAT ARE READY TO EXECUTE IN THE SYSTEM ARE KEPT IN THE
  545. READY QUEUE.  ╘HE ╨├┬ OF THE ╬ULL PROCESS ACTS AS THE HEAD FOR THIS QUEUE, AND
  546. IS ALSO AN ACTIVE NODE IN THE QUEUE (A SMALL BUT HARMLESS KLUGE).  ╘HE POINTER
  547. TO THE ACTIVE PROCESS IS KEPT IN A KERNEL-ZERO-PAGE VARIABLE, AND SWEEPS
  548. THROUGH THE CIRCULARLY LINKED READY-PROCESS LIST TO ACTIVATE NEW PROCESSES.
  549. ╘HE ACTIVE ╨├┬ IS NOT REMOVED FROM THE READY LIST WHILE IT IS ACTIVE.
  550.  
  551. 3.2.2. ├╧╬╘┼╪╘-├╠┴╙╙ ╞╔┼╠─╙
  552.  
  553. ╘HE NEXT FOUR FIELDS, OF THE CLASS "CTXT", STORE THE "CONTEXT" OF A PROCESS
  554. THAT IS NOT STORED ON THE PROCESS' STACK WHEN IT IS NOT EXECUTING.  ╘HESE
  555. FIELDS INCLUDE SPACE FOR THE STACK POINTER, THE STACK PAGE, THE ZEROPAGE, AND
  556. THE CONTENTS OF THE ══╒ REGISTER AT LOCATION $D506.  ╘HE STACK POINTER IS
  557. WHAT WAS IN THE ╙╨ REGISTER OF THE ├╨╒ WHEN THE PROCESS LAST PAUSED.  ╘HE
  558. STACK PAGE AND THE ZEROPAGE VALUES ARE THE VALUES IN ══╒ REGISTERS $D505 AND
  559. $D507, RESPECTIVELY; THESE ARE THE PAGE NUMBERS OF THE PAGES IN ╥┴═0 MEMORY
  560. THAT ARE ALLOCATED TO A PROCESS.  ╘HESE PAGES CAN ONLY BE IN ╥┴═0 UNLESS
  561. COMMON MEMORY IS DISABLED, FOR HARDWARE REASONS.  ╔ MAY ALLOW THESE PAGES TO
  562. BE IN EITHER ╥┴═0 OR ╥┴═1 IF THERE IS A NEED LATER.  ╘HE $D506 REGISTER OF
  563. THE ══╒ STORES THE MOST-SIGNIFICANT BITS OF THE ╥┴═ BANK THAT IS SELECTED IF
  564. YOU HAVE EXPANDED INTERNAL MEMORY ON YOUR 128 (A LA ╘WIN├ITIES-128) AND THE
  565. BANK SELECTION FOR ╥┼╒ (─═┴) OPERATIONS.
  566.  
  567. ╘HE REST OF A PROCESS' CONTEXT IS STORED ON ITS STACK.  ╚ERE IS WHAT A
  568. PROCESS' STACK LOOKS LIKE JUST AFTER IT HAS BEEN CREATED:
  569.  
  570. ┴──╥   ╙╨-╥┼╠   ─┼╙├╥╔╨╘╔╧╬
  571. ----   ------   ------------
  572. $FF    SP+09    EXITADDR-1.H
  573. $FE    SP+08    EXITADDR-1.L
  574. $FD    SP+07    PC.H
  575. $FC    SP+06    PC.L
  576. $FB    SP+05    STATUS REGISTER
  577. $FA    SP+04    .┴
  578. $F9    SP+03    .╪
  579. $F8    SP+02    .┘
  580. $F7    SP+01    $FF00 SAVE
  581. $F6    SP+00    -EMPTY-
  582.  
  583. ╘HE "EXITADDR" IS THE ADDRESS OF THE ROUTINE IN THE KERNEL THAT WILL TERMINATE
  584. A PROCESS IF IT EXECUTES AN ╥╘╙ FROM ITS MAIN ROUTINE.  ╘HE ADDRESS IS IN THE
  585. REGULAR LOW-HIGH ORDER (ALTHOUGH IT IS PUSHED ON HIGH-LOW SINCE THE STACK
  586. GROWS DOWNWARD IN MEMORY) BUT THE VALUE PUSHED IS ACTUALLY ONE LESS THAN THE
  587. ADDRESS OF THE ROUTINE, BECAUSE THIS IS WHAT ╩╙╥ PUSHES ONTO THE STACK AND
  588. THIS IS WHAT ╥╘╙ EXPECTS TO FIND.  ╘HE "PC" LOW AND HIGH FIELDS GIVE THE
  589. ADDRESS OF THE NEXT INSTRUCTION TO BE EXECUTED BY THE PROCESS WHEN IT IS
  590. ACTIVATED.  ╫HEN THE PROCESS IS FIRST CREATED, THIS WILL BE THE ADDRESS OF THE
  591. FIRST INSTRUCTION.  ╘HE "PC" VALUE IS THE ACTUAL ADDRESS, NOT ONE BEFORE,
  592. BECAUSE THIS IS WHAT A HARDWARE INTERRUPT PUSHES ONTO THE STACK, AND THIS IS
  593. WHAT THE ╥╘╔ INSTRUCTION EXPECTS TO FIND.
  594.  
  595. ╘HE "STATUS REGISTER", ".┴", ".╪", AND ".┘" FIELDS CONTAIN THE VALUES TO BE
  596. LOADED INTO THE CORRESPONDING REGISTERS INSIDE OF THE ├╨╒ WHEN THE PROCESS IS
  597. ACTIVATED.  ╞OR A NEW PROCESS, THESE VALUES ARE ALL ZERO.
  598.  
  599. ╘HE "$FF00 SAVE" IS THE VALUE TO BE LOADED INTO THE $FF00 "SHADOW" REGISTER OF
  600. THE ══╒ WHEN THE PROCESS IS ACTIVATED.  ╘HIS GIVES THE MEMORY CONTEXT THAT THE
  601. PROCESS IS TO EXECUTE IN.  ┴S THE KERNEL CURRENTLY ONLY WORKS WITH ONE BANK
  602. CONFIGURATION (╥┴═0, ╬╧ ┬┴╙╔├ ╥╧═, ╔/╧ ENABLED, ╦┼╥╬┴╠ ╥╧═ ENABLED), THIS IS
  603. THE VALUE PUT HERE WHEN A PROCESS IS CREATED.
  604.  
  605. ╘HE FINAL FIELD IS "-EMPTY-" BECAUSE THE STACK POINTER IN THE 6502 POINTS TO
  606. THE NEXT LOCATION IN STACK MEMORY THAT WILL BE USED.  ┴LL OTHER VALUES IN THE
  607. STACK ARE RELATIVE TO THIS.  ╒PON STARTUP, THE STACK-POINTER FIELD OF THE
  608. PROCESS CONTROL BLOCK WILL BE SET TO $F6, WHICH IS WHAT THE TABLE ABOVE
  609. SHOWS.
  610.  
  611. ╘HE STACK CONTENTS LOOK EXACTLY THE SAME AFTER A PROCESS HAS BEEN INTERRUPTED
  612. BY A HARDWARE INTERRUPT, EXCEPT THAT THE STACK POINTER WILL LIKELY BE LOWER IN
  613. THE STACK MEMORY, SO THE ABSOLUTE ADDRESSES IN STACK MEMORY IN THE ABOVE TABLE
  614. NO LONGER APPLY AND THE "EXITADDR" BYTES ARE NOT PART OF THE INTERRUPT
  615. CONTEXT.  ╘HAT THINGS LOOK THE SAME IS NO COINCIDENCE; ON STARTUP, WE SET UP
  616. THE STACK TO MAKE THINGS LOOK AS IF AN INTERRUPT HAD JUST OCCURRED, AND TO
  617. START A PROCESS EXECUTING, WE EXECUTE THE CODE THAT RETURNS FROM AN INTERRUPT,
  618. WHICH LOADS THE "CONTEXT" THAT IS ON THE STACK INTO THE PROCESS REGISTERS, AND
  619. WE ARE READY TO ROCK.
  620.  
  621. ╘HE ABOVE STACK ORGANIZATION IS EXACTLY THE SAME AS IT IS FOR PROCESSING
  622. INTERRUPTS NORMALLY USING THE ├OMMODORE-╦ERNAL ENVIRONMENT ON THE 128, AND
  623. THIS TOO IS NO COINCIDENCE BECAUSE THE CODE THAT SETS UP THE STACK LIKE THIS
  624. UPON AN INTERRUPT IS BURNED INTO THE ╦ERNAL ╥╧═ AND THERE IS VERY LITTLE THAT
  625. ╔ CAN DO ABOUT IT.  ╞ORTUNATELY, THE ORGANIZATION IS JUST FINE FOR OUR
  626. PURPOSES.
  627.  
  628. 3.2.3. ╙├╚┼─╒╠┼-├╠┴╙╙ ╞╔┼╠─╙
  629.  
  630. ╘HE NEXT THREE FIELDS, OF CLASS "SCHED", ARE USED TO SCHEDULE THE PROCESS.
  631. ╘HE "PCB╨RIORITY" FIELD GIVES THE RELATIVE PRIORITY OF THE PROCESS ACCORDING
  632. TO THE SCHEME ALREADY DISCUSSED.  ╘HE "PCB├OUNTDOWN" FIELD IS USED TO KEEP
  633. COUNT OF THE NUMBER OF REMAINING TIMES THAT THE PROCESS WILL HAVE TO BE
  634. BYPASSED IN CYCLING THROUGH THE READY QUEUE BEFORE THE PROCESS WILL BE
  635. ACTIVATED AGAIN.  ╫HEN A PROCESS GIVES UP THE ├╨╒ UPON THE EXPIRATION OF ITS
  636. TIME QUANTUM, THE "PCB├OUNTDOWN" FIELD IS LOADED WITH THE PCB╨RIORITY OF THE
  637. PROCESS.  ╫HEN THE "PCB├OUNTDOWN" VALUE REACHES ZERO, THE PROCESS IS SELECTED
  638. FOR ACTIVATION.
  639.  
  640. ╘HE "PCB╫AKEUP╘IME" FIELD IS USED WITH THE ─ELAY() KERNEL CALL TO INDICATE THE
  641. ABSOLUTE SYSTEM TIME WHEN THE PROCESS SHOULD BE ACTIVATED AGAIN.  ╘HE CURRENT
  642. TIME IN THE SYSTEM IS KEPT IN A 16-BIT KERNEL VARIABLE, AND WRAPS AROUND EVERY
  643. 18.2 MINUTES.  ╔F THE PROCESS IS NOT CURRENTLY TIME-DELAYED, THEN THE
  644. ╫AKEUP╘IME FIELD IS NOT USED (IN FACT, THE MEMORY MAY BE USED TO RECORD OTHER
  645. STATUS INFORMATION).
  646.  
  647. 3.2.4. ╔╨├-├╠┴╙╙ ╞╔┼╠─╙
  648.  
  649. ╘HE EIGHT EIGHT FIELDS, OF CLASSES "IPC" AND "IPC/Q" ARE USED FOR INTERPROCESS
  650. COMMUNICATION (MESSAGE PASSING).  ╘HE FIRST TWO FIELDS, "PCB╙END═SG╨TR" AND
  651. "PCB╥ECV═SG╨TR", ARE USED FOR STORING TEMPORARY VALUES FOR HANDLING MESSAGE
  652. REQUESTS; THE FOUR "IPC/Q"-CLASS FIELDS ARE USED TO IMPLEMENT THE HEAD OF A
  653. QUEUE OF PROCESSES THAT ARE WAITING TO COMMUNICATE WITH THE CURRENT PROCESS,
  654. AND THE "PCB┬LOCKED╧N" FIELD INDICATES WHICH PROCESS THIS PROCESS IS WAITING
  655. TO COMMUNICATE WITH, IF THE CURRENT PROCESS IS WAITING.  ╘HE FIRST TWO FIELDS
  656. ACTUALLY OVERLAP WITH EACH OTHER AND WITH THE "PCB╫AKEUP╘IME" FIELD DISCUSSED
  657. EARLIER.  ╘HIS IS OKAY SINCE NONE OF THE FIELDS WILL STORE ACTIVE STATUS
  658. INFORMATION AT THE SAME TIME.  ╘HE LAST FIELD, "PCB╥ECEIVE╞ROM" IS NOT USED AT
  659. THIS TIME, BUT WILL BE USED IN THE FUTURE FOR AN PRIMITIVE TO RECEIVE A
  660. MESSAGE ONLY FROM A SPECIFIC PROCESS.  ╘HE INTERPROCESS COMMUNICATION IS
  661. DISCUSSED IN MUCH GREATER DETAIL LATER.
  662.  
  663. 3.2.5. ╨╥╧├-├╠┴╙╙ ╞╔┼╠─╙
  664.  
  665. ╘HE FINAL TWO FIELDS, OF CLASS "PROC", STORE INFORMATION ABOUT THE STATUS OF
  666. THE PROCESS.  ╔ GUESS THE SAME CAN BE SAID OF ALL THE OTHER FIELDS.  ┴NYWAY,
  667. THE "PCB╨ARENT" FIELD INDICATES WHICH PROCESS IS THE PROCESS THAT CREATED THE
  668. CURRENT PROCESS, AND THE RETURN VALUE FOR THE ═Y╨ARENT╨ID() KERNEL CALL IS
  669. TAKEN FROM THIS FIELD.
  670.  
  671. ╘HE "PCB╙TATE" FIELD GIVES THE CURRENT STATE OF THE PROCESS.  ╚ERE ARE THE
  672. DIFFERENT POSSIBLE PROCESS STATES:
  673.  
  674. ╙╘┴╘┼ ╬┴═┼        ├╧─┼
  675. ---------------   ----
  676. ╙╘┴╘┼_╥┼┴─┘       $C0
  677. ╙╘┴╘┼_╙┼╬─        $C1
  678. ╙╘┴╘┼_╥┼├┼╔╓┼     $C2
  679. ╙╘┴╘┼_╥┼╨╠┘       $C3
  680. ╙╘┴╘┼_─┼╠┴┘       $C4
  681. ╙╘┴╘┼_╙╒╙╨┼╬─┼─   $C5
  682.  
  683. ╘HE ╙╘┴╘┼_╥┼┴─┘ STATE MEANS THAT THE PROCESS IS IN THE READY QUEUE.  ╘HE
  684. ╙╘┴╘┼_╙┼╬─, ╙╘┴╘┼_╥┼├┼╔╓┼, AND ╙╘┴╘┼_╥┼╨╠┘ STATES MEAN THAT A PROCESS IS
  685. WAITING FOR SOME INTERPROCESS COMMUNICATION PRIMITIVE TO BE CALLED BY THE
  686. PROCESS THAT IT IS COMMUNICATING WITH.  ╘HE ╙╘┴╘┼_─┼╠┴┘ STATE MEANS THAT THE
  687. PROCESS HAS CALLED THE ─ELAY() PRIMITIVE AND IS WAITING FOR SOME PERIOD OF
  688. REAL TIME TO PASS BEFORE IT CAN BE ACTIVATED AGAIN.  ╘HE ╙╘┴╘┼_╙╒╙╨┼╬─┼─ STATE
  689. MEANS THAT A PROCESS HAS CALLED THE ╙USPEND() OR ┼XIT() PRIMITIVE AND WILL
  690. NEVER BE MADE ACTIVE AGAIN (CURRENTLY, ╙USPEND() AND ┼XIT() MEAN THE SAME
  691. THING).
  692.  
  693. ╘HE STATE INFORMATION IS NEEDED FOR SOME OPERATIONS, AND WILL DEFINITELY BE
  694. NEEDED BY A ╦ILL()-PROCESS OPERATION, TO FIND OUT WHAT STATE A PROCESS IS IN
  695. SO THAT IT CAN BE REMOVED FROM ANY QUEUE OR WHATEVER IT IS IN, IN ORDER TO
  696. OBLITERATE ALL INFORMATION ABOUT THE PROCESS FROM THE SYSTEM.  ├URRENTLY,
  697. THERE IS NO ╦ILL() CALL.
  698.  
  699. 3.3. ╘┴╙╦ ├╥┼┴╘╔╧╬
  700.  
  701. ╫HEN THE USER CALLS FOR THE CREATION OF A NEW PROCESS IN THE SYSTEM, LOTS OF
  702. STUFF HAS TO HAPPEN.  ╞IRST, MEMORY FOR THE PROCESS CONTROL BLOCK, ZERO PAGE,
  703. AND STACK PAGE MUST BE ALLOCATED.  ├URRENTLY, THIS ALLOCATION IS PERFORMED
  704. VERY SIMPLY, BY KEEPING A PAGE POINTER AND INCREMENTING IT EVERY TIME A PAGE
  705. IS ALLOCATED.  ╘HE PROCESS CONTROL BLOCK ENDS UP GETTING ALLOCATED 256 BYTES
  706. EVEN THOUGH IT ACTUALLY REQUIRES MUCH LESS THAN THAT.  ╘HUS, EACH NEW PROCESS
  707. CHEWS UP 768 BYTES OF MEMORY SPACE (PLUS CODE).  ┴LSO, THERE IS CURRENTLY NO
  708. MECHANISM FOR RECOVERING THE MEMORY ALLOCATED TO A PROCESS, WHICH IS OKAY
  709. SINCE THE MECHANISM FOR ┼XIT()ING A PROCESS IS INCOMPLETE TOO.
  710.  
  711. ╘HE ADDRESS THAT A ╨├┬ GETS ALLOCATED AT IS USED FOR THE PROCESS' ╨╔─ (PROCESS
  712. IDENTIFIER).  ╘HIS IS PARTICULARLY USEFUL SINCE THE REAL PURPOSE OF A ╨╔─ IS
  713. TO CONVENIENTLY LOCATE THE PROCESS CONTROL BLOCK.  ╘HIS WILL HAVE TO CHANGE
  714. IN THE FUTURE, HOWEVER, SINCE THE ╨╔─S WILL ALSO HAVE TO LOCATE THE MACHINE
  715. THAT A PROCESS IS ON.
  716.  
  717. ╘HEN THE PROCESS CONTROL BLOCK MUST BE INITIALIZED.  ╔T IS INITIALIZED AS
  718. FOLLOWS:
  719.  
  720. ╞╔┼╠─            ╙╔┌   ├╠┴╙╙   ╔╬╔╘╔┴╠ ╓┴╠╒┼
  721. --------------   ---   -----   --------------
  722. PCB╬EXT            2   QUEUE   0
  723. PCB╨REV            2   QUEUE   0
  724. PCB╔S╚EAD          1   QUEUE   0
  725. PCB╤├OUNT          1   QUEUE   0
  726. PCB╙╨              1   CTXT    $F6
  727. PCB╙TACK╨AGE       1   CTXT    SET TO NEWLY ALLOCATED SPACE
  728. PCB┌ERO╨AGE        1   CTXT    SET TO NEWLY ALLOCATED SPACE
  729. PCB─506            1   CTXT    $04
  730. PCB╨RIORITY        1   SCHED   SET TO THE GIVEN ARGUMENT
  731. PCB├OUNTDOWN       1   SCHED   SET TO THE SAME VALUE AS "PCB╨RIORITY"
  732. PCB╫AKEUP╘IME      2   SCHED   0 (OVERLOADED FIELD)
  733. PCB╙END╤╚EAD       2   IPC/Q   SET BY THE ╤UEUE╔NIT() FUNCTION FOR EMPTY QUEUE
  734. PCB╙END╤╘AIL       2   IPC/Q   SET BY THE ╤UEUE╔NIT() FUNCTION FOR EMPTY QUEUE
  735. PCB╙END╤╞LAG       1   IPC/Q   SET BY THE ╤UEUE╔NIT() FUNCTION FOR EMPTY QUEUE
  736. PCB╙END╤├OUNT      1   IPC/Q   SET BY THE ╤UEUE╔NIT() FUNCTION FOR EMPTY QUEUE
  737. PCB┬LOCKED╧N       2   IPC     0
  738. PCB╥ECEIVE╞ROM     2   IPC     0
  739. PCB╨ARENT          2   PROC    SET TO THE ID OF THE CREATOR PROCESS
  740. PCB╙TATE           1   PROC    ╙╘┴╘┼_╙╒╙╨┼╬─┼─
  741.  
  742. ╘HE VALUES ON THE TOP OF THE STACK PAGE ARE ALSO INITIALIZED FOR THE NEW
  743. PROCESS, AS FOLLOWS:
  744.  
  745. ┴──╥   ╙╨-╥┼╠   ─┼╙├╥╔╨╘╔╧╬       ╔╬╔╘╔┴╠ ╓┴╠╒┼
  746. ----   ------   ---------------   --------------
  747. $FF    SP+09    EXITADDR-1.H      HIGH BYTE OF ┼XIT┴DDR-1: THE EXIT ROUTINE
  748. $FE    SP+08    EXITADDR-1.L      LOW BYTE OF ┼XIT┴DDR-1: THE EXIT ROUTINE
  749. $FD    SP+07    PC.H              HIGH BYTE OF THE CODE-EXECUTION ADDRESS
  750. $FC    SP+06    PC.L              HIGH BYTE OF THE CODE-EXECUTION ADDRESS
  751. $FB    SP+05    STATUS REGISTER   $00
  752. $FA    SP+04    .┴                $00
  753. $F9    SP+03    .╪                $00
  754. $F8    SP+02    .┘                $00
  755. $F7    SP+01    $FF00 SAVE        $0E  (╦ERNAL ╥╧═, ╔/╧, REST ╥┴═0)
  756. $F6    SP+00    -EMPTY-           --
  757.  
  758. ┴ND NOW, THE NEW PROCESS IS READY FOR ACTION.  ╫E INSERT IT INTO THE READY
  759. QUEUE IN THE NEXT POSITION AFTER THE CURRENT PROCESS, SET ITS STATE TO
  760. ╙╘┴╘┼_╥┼┴─┘ (ACTUALLY, BOTH OF THESE OPERATIONS ARE PERFORMED BY THE
  761. ═AKE╥EADY() FUNCTION, WHICH IS GENERALLY USEFUL AND IS CALLED FROM A NUMBER OF
  762. PLACES) AND THEN WE EXIT BACK TO THE CALLING PROCESS, RETURNING THE PROCESS ID
  763. OF THE CALLING PROCESS.  ╔ SHOULD CHANGE THIS A LITTLE BIT IN THE FUTURE, TO
  764. MAKE IT EXIT TO THE NEWLY CREATED CHILD PROCESS IF THE PRIORITY OF THE CHILD
  765. PROCESS IS GREATER THAN THE PRIORITY OF THE PARENT.
  766.  
  767. 3.4. ├╧╬╘┼╪╘ ╙╫╔╘├╚╔╬╟
  768.  
  769. ├ONTEXT SWITCHING DESCRIBES THE PROCEDURE OF SWITCHING CONTROL OF THE
  770. PROCESSOR FROM A USER PROCESS TO THE KERNEL AND THEN SWITCHING CONTROL BACK TO
  771. A USER PROCESS.  ╬ORMALLY, THERE IS ONLY ONE "STYLE" OF CONTEXT SWITCHING IN A
  772. SYSTEM, BUT FOR A COUPLE OF DESIGN REASONS, ┬╧╙ ACTUALLY HAS THREE "STYLES" OF
  773. CONTEXT SWITCHING: ╔╥╤ SWITCHING, ╩╙╥ SWITCHING, AND QUICK ╩╙╥ SWITCHING.
  774. ╔╥╤-STYLE SWITCHING IS THE ONE TYPE NORMALLY IMPLEMENTED IN OPERATING SYSTEMS
  775. FOR OTHER ARCHITECTURES, SO IT WILL BE THE ONE THAT WE COVER FIRST.
  776.  
  777. ╔╥╤-STYLE CONTEXT SWITCHING INVOLVES SAVING THE FULL CONTEXT OF A PROCESS ONTO
  778. ITS STACK AND INTO ITS PROCESS CONTROL BLOCK, SWITCHING INTO THE KERNEL, DOING
  779. WORK, SWITCHING BACK OUT OF THE KERNEL, AND RELOADING THE FULL CONTEXT OF A
  780. USER PROCESS AND ACTIVATING TO IT.  ┴LL OF THE WORK OF SAVING AND RESTORING
  781. THE THE STACK PORTION OF A PROCESS' CONTEXT IS HANDLED BY THE ╥╧═ ROUTINES FOR
  782. ╔╥╤ (AND ╬═╔ AND ┬╥╦) HANDLING.  ┴LL WE HAVE TO DO IS LOCATE THE CURRENT
  783. PROCESS CONTROL BLOCK, SAVE THE ZERO-PAGE, STACK-PAGE, STACK-POINTER, AND
  784. $D506 REGISTERS INTO THE ╨├┬, AND LOAD A $00 INTO THE ZERO-PAGE ══╒ REGISTER
  785. TO SWITCH TO THE KERNEL'S ZEROPAGE (WHERE SOME OF THE KERNEL'S VARIABLES ARE
  786. STORED).  ╬OTE THAT THE INTERRUPT WILL BE EXECUTED USING THE USER PROCESS'
  787. STACK; THEREFORE, ENOUGH SPACE SHOULD ALWAYS BE AVAILABLE ON USER STACKS TO
  788. HANDLE THIS SYSTEM OVERHEAD.
  789.  
  790. ╫HEN WE ARE DONE PROCESSING THE INTERRUPT, WE EXECUTE THE PRIORITY-MANAGEMENT
  791. ALGORITHM THAT WAS DESCRIBED EARLIER TO SELECT THE NEXT PROCESS TO ACTIVATE,
  792. AND THEN RESTORE THE ZERO-PAGE, STACK-PAGE, STACK-POINTER, AND $D506 REGISTERS
  793. AND EXECUTE THE ╥╧═ STACK-HANDLING CODE FOR EXITING FROM AN INTERRUPT.  ╬OTE
  794. THAT THERE'S A CHANCE THAT WE MIGHT WELL BE EXITING TO A DIFFERENT USER
  795. PROCESS FROM THE ONE THAT WAS ACTIVE WHEN THE INTERRUPT OCCURRED.  ╘HERE
  796. AREN'T MANY REGISTERS TO SAVE AND RESTORE, SO CONTEXT SWITCHING HAS A FAIRLY
  797. LOW OVERHEAD, SO THERE IS NO PROBLEM IN DOING IT (AT LEAST) SIXTY TIMES A
  798. SECOND.
  799.  
  800. ╩╙╥-STYLE CONTEXT SWITCHING IS PRETTY MUCH THE SAME AS ╔╥╤-STYLE CONTEXT
  801. SWITCHING, EXCEPT THAT THE STACK WILL NOT HAVE MOST OF THE PROCESSOR REGISTERS
  802. ALREADY SAVED ON IT; IT WILL ONLY HAVE THE RETURN ADDRESS THAT PERFORMED THE
  803. ╩╙╥.  ╔MMEDIATELY UPON ENTERING THE KERNEL, INTERRUPTS ARE DISABLED TO PREVENT
  804. ALL SORTS OF BAD THINGS FROM HAPPENING.  ╘HEN A FUNCTION IS CALLED,
  805. ┼NTER╦ERNEL(), WHICH WILL PULL THE RETURN ADDRESS OF THE PROCESS THAT CALLED
  806. THE ╩╙╥ OFF THE STACK AND INCREMENT IT BY ONE (SINCE WE WILL BE EXITING BY
  807. USING AN ╥╘╔ INSTRUCTION RATHER THAN AN ╥╘╙) AND SAVES THE OTHER PROCESSOR
  808. REGISTERS ONTO THE STACK IN THE SAME WAY THAT THE INTERRUPT-HANDLING CODE IN
  809. ╥╧═ WOULD.  ╘HEN WE SAVE THE FOUR ADDITIONAL REGISTERS INTO THE ╨├┬ AS BEFORE,
  810. ACTIVATE THE KERNEL ZEROPAGE, AND WE ARE SWITCHED IN.
  811.  
  812. ╘HIS STYLE OF CONTEXT SWITCHING IS USED FOR KERNEL CALLS THAT WILL CAUSE THE
  813. CALLING PROCESS TO BLOCK (LIKE A NON-ZERO ─ELAY()).  ╔T WOULD HAVE BEEN
  814. POSSIBLE TO ORGANIZE THE KERNEL CALLS TO BE ENTERED BY EXECUTING A ┬╥╦
  815. INSTRUCTION, WHICH WOULD HAVE CAUSED THE STACK TO BE ALREADY SET UP IN THE
  816. SAME WAY AS WITH ╔╥╤ INTERRUPTS, BUT ╔ DECIDED AGAINST THIS FOR TWO REASONS:
  817. EFFICIENCY, IT WOULD HAVE BEEN SLOWER TO DO THIS, AND DEBUGGING (SECURITY?),
  818. SINCE ╔ ONLY WANT THE ┬╥╦ CONDITION TO SIGNAL A BUG IN THE CODE.  ╘HE EXIT
  819. FROM THIS TYPE OF CONTEXT SWITCH IS THE SAME AS FOR THE ╔╥╤ STYLE OF CONTEXT
  820. SWITCH, SINCE THINGS ARE RIGGED TO END UP LOOKING THE SAME ON THE STACK.  ╘HIS
  821. IS A GOOD THING, SINCE THE ACTION THAT WILL CAUSE A ─ELAY()ED PROCESS TO BE
  822. RE-ACTIVATED WILL, IN FACT, BE AN ╔╥╤ INTERRUPT.
  823.  
  824. ╤UICK ╩╙╥-STYLE CONTEXT SWITCHING IS USED FOR KERNEL CALLS THAT WILL NOT BLOCK
  825. OR CAUSE A NEW PROCESS TO BE ACTIVATED WHEN THEY FINISH, SUCH AS ═Y╨ID() OR
  826. (CURRENTLY) ├REATE().  ╬O CONTEXT HAS TO BE SAVED SINCE THE FUNCTION WILL GET
  827. IN AND OUT VERY QUICKLY; ALL WE HAVE TO DO IS SWITCH TO THE KERNEL'S ZEROPAGE
  828. AND THEN SWITCH BACK TO THE USER'S ZEROPAGE BEFORE EXIT.
  829.  
  830. ╘HERE'S ONE MORE NOTE TO MAKE ABOUT RETURN VALUES.  ╞OR THE QUICK ╩╙╥-STYLE
  831. CONTEXT SWITCH, THERE IS NO PROBLEM WITH RETURN VALUES, SINCE WE JUST HAVE TO
  832. LOAD THEM INTO THE PROCESSOR REGISTERS AND EXIT.  ╫ITH THE FULL ╩╙╥-STYLE
  833. CONTEXT SWITCH, THE RETURN VALUES HAVE TO BE PUT ONTO THE USER STACK INTO THE
  834. POSITIONS IN THE STACK MEMORY THE HOLD THE PROCESSOR REGISTER CONTENTS, SINCE
  835. THESE VALUES WILL BE WHAT ARE RESTORED INTO THE PROCESSOR IMMEDIATELY UPON THE
  836. RETURN TO THE USER PROCESS.  ╘HERE ARE NO RETURN VALUES ASSOCIATED WITH THE
  837. ╔╥╤ STYLE OF CONTEXT SWITCHING (AND THERE'D BETTER NOT BE), SINCE AN INTERRUPT
  838. CAN HAPPEN AT ANY POINT IN THE EXECUTION OF A USER PROCESS.
  839.  
  840. 3.5. ─┼╠┴┘ ╨╥╔═╔╘╔╓┼
  841.  
  842. ╘HERE ARE TWO COMPLEMENTARY HALVES TO THE IMPLEMENTION OF THE ─ELAY()
  843. PRIMITIVE: THE HALF THAT IS CALLED BY THE USER AND CAUSES A PROCESS TO GO TO
  844. SLEEP, AND THE HALF THAT WAKES UP A SLEEPING PROCESS AT THE CORRECT TIME.
  845. ╘HIS LATTER HALF IS EXECUTED BY THE 60-╚Z SYSTEM INTERRUPT.
  846.  
  847. 3.5.1. ╒╙┼╥ ╚┴╠╞ ╧╞ ╘╚┼ ─┼╠┴┘ ╨╥╔═╔╘╔╓┼
  848.  
  849. ╘HE FIRST THING THAT THE USER HALF OF THE ─ELAY() PRIMITIVE DOES IS CHECK TO
  850. SEE IF THE DELAY PERIOD IS ZERO JIFFIES.  ╔F IT IS, THEN THE PRIMITIVE RETURNS
  851. IMMEDIATELY TO THE CALLING PROCESS WITHOUT RESCHEDULING (WITHOUT SKIPPING TO
  852. THE NEXT READY PROCESS IN LINE).  ╔ MAY CHANGE THIS SEMANTIC, BECAUSE IT IS
  853. OFTEN USEFUL TO HAVE A PRIMITIVE THAT YEILDS PROCESS EXECUTION TO THE NEXT
  854. READY PROCESS WITHOUT ACTUALLY BLOCKING THE CURRENT PROCESS.
  855.  
  856. ╔F THE DELAY PERIOD IS LONGER THAN ZERO JIFFIES, THEN THE CURRENT PROCESS IS
  857. SUSPENDED AND REMOVED FROM THE READY QUEUE, AND THE ABSOLUTE TIME THAT THE
  858. PROCESS IS TO BE REAWAKENED IS CALCULATED AND PUT INTO THE "PCB╫AKEUP╘IME"
  859. FIELD OF THE ╨├┬ FOR THE CURRENT PROCESS.  ╘HE ABSOLUTE WAKEUP TIME IS
  860. CALCULATED, OF COURSE, BY ADDING THE NUMBER OF JIFFIES TO DELAY TO THE CURRENT
  861. ABSOLUTE TIME, WHICH IS MAINTAINED BY THE SYSTEM AND INCREMENTED ON EVERY
  862. (60 ╚Z) SYSTEM INTERRUPT.
  863.  
  864. ╘HEN THE CURRENT PROCESS CONTROL BLOCK IS INSERTED INTO THE DELAY QUEUE AT THE
  865. CORRECT POSITION.  ╘HE DELAY QUEUE IS A QUEUE (IMPLEMENTED IN THE STANDARD
  866. WAY) OF PROCESS CONTROL BLOCKS FOR PROCESSES WHICH ARE ASLEEP, ORDERED BY THE
  867. ABSOLUTE WAKEUP TIME OF EACH PROCESS SUCH THAT THE PROCESS THAT WILL BE
  868. AWAKENED AT THE NEAREST TIME IN THE FUTURE IS AT THE HEAD OF THE LIST AND THAT
  869. THE PROCESS WHICH WILL BE AWAKENED AT THE FARTHEST POINT IN THE FUTURE IS AT
  870. THE TAIL.  ╘HE FOLLOWING DIAGRAM GIVES AN EXAMPLE:
  871.  
  872. ├URRENT╘IME = 2016
  873.  
  874.     +---------+      +---------+      +---------+      +---------+
  875. --->▄ ╨ROC ┴  ▄----->▄ ╨ROC ┬  ▄----->▄ ╨ROC ├  ▄----->▄ ╨ROC ─  ▄
  876.     ▄ WAKEUP: ▄      ▄ WAKEUP: ▄      ▄ WAKEUP: ▄      ▄ WAKEUP: ▄
  877. <---▄ @ 2345  ▄<-----▄ @ 2765  ▄<-----▄ @ 54999 ▄<-----▄ @ 441   ▄
  878.     +---------+      +---------+      +---------+      +---------+
  879.     (CT+5.5SEC)      (CT+12.5SEC)     (CT+14.7MIN)     (CT+17.8MIN)
  880.  
  881. ╘HERE IS A RUB HERE: ONLY 16 BITS ARE USED FOR STORING TIMES, WHICH EQUALS
  882. ABOUT 18.2 MINUTES, SO WE HAVE TO WORRY ABOUT TIME QUANTITIES OVERFLOWING AND
  883. WRAPPING AROUND.  ╞OR EXAMPLE, IF THE CURRENT TIME IS 48232 AND A PROCESS
  884. WANTS TO SLEEP FOR 18000 JIFFIES (5 MINUTES), THEN ITS WAKEUP TIME WOULD BE AT
  885. 696 JIFFIES, ACCOUNTING FOR THE 16-BIT WRAPAROUND, WHICH IS A LOWER NUMERICAL
  886. VALUE THAN THE CURRENT TIME, OR THAN THE WAKEUP TIME OF ANY OTHER PROCESS THAT
  887. WILL WAKE UP BEFORE THE CURRENT-TIME WRAPAROUND.  ╔N FACT, ALL TIMERS HAVE
  888. THIS WRAPAROUND PROBLEM (ALTHOUGH WITH 64-BIT TIMES, WRAPAROUND PERIODS WOULD
  889. BE EXPRESSED IN MILLIONS OF MILLENNIA RATHER THAN IN MINUTES).  ╙IXTEEN BITS
  890. IS A GOOD NUMBER OF BITS TO USE, HOWEVER, BECAUSE THAT IS THE MAXIMUM DELAY
  891. PERIOD (2^16-1).
  892.  
  893. ╫HEN WE INSERT A NEW PROCESS INTO THE DELAY QUEUE, WE SCAN THE DELAY QUEUE
  894. FROM THE HEAD AND CONTINUE UNTIL WE FIND A RECORD THAT HAS A TIME THAT IS
  895. HIGHER THAN OR EQUAL TO THE WAKEUP TIME OF THE NEW PROCESS (OR WE HIT THE END
  896. OF THE QUEUE).  ╘HEN, WE INSERT THE NEW PROCESS IMMEDIATELY BEFORE THIS
  897. POINT.  ╘O HANDLE THE WRAPAROUND PROBLEM, ALL COMPARISONS OF WAKEUP TIMES ARE
  898. DONE USING 17 BITS (WELL, REALLY 24 BITS).  ╞OR EACH VALUE IN THE COMPARISON,
  899. WE ADD 65536 TO IT (SET ITS 17TH BIT) IF THE VALUE IS LESS THAN THE CURRENT
  900. TIME.  ╫E DON'T HAVE TO WORRY ABOUT THE CURRENT TIME CHANGING WHILE WE ARE
  901. DOING THIS, BECAUSE INTERRUPTS WILL BE DISABLED FOR THE ENTIRE TIME THAT
  902. WE ARE EXECUTING THE SYSTEM CALL, AS PER USUAL.  ╘HINGS COULD GO HORRIBLY
  903. WRONG ANYWAY IF INTERRUPTS WERE NOT DISABLED.
  904.  
  905. ╧KAY, SO NOW OUR DELAYING PROCESS IS REMOVED FROM THE READY QUEUE, ITS
  906. COMPLETE CONTEXT IS SAVED, AND IT IS PUT INTO THE DELAY QUEUE AT THE RIGHT
  907. SPOT.  ╙O, SET THE ACTIVE PROCESS POINTER TO THE NEXT READY PROCESS IN THE
  908. SYSTEM AND FINISH BY ACTIVATING THE NEXT READY PROCESS.
  909.  
  910. 3.5.2. ╙┘╙╘┼═ ╚┴╠╞ ╧╞ ╘╚┼ ─┼╠┴┘ ╨╥╔═╔╘╔╓┼
  911.  
  912. ─URING EACH 60-╚Z SYSTEM INTERRUPT, THE CURRENT TIME (JIFFY COUNTER) IS
  913. INCREMENTED BY ONE.  ╬OTE THAT SINCE THIS TIMER IS ONLY 16 BITS WIDE, IT IS
  914. NOT SUITABLE FOR KEEPING TRACK OF THE CURRENT TIME OF DAY; FOR THIS PURPOSE,
  915. THE ╘╧─ CLOCKS IN THE ├╔┴ CHIPS SHOULD (AND WILL) BE USED.  ╘HE JIFFY COUNTER
  916. MAY ALSO BE INACCURATE IF INTERRUPTS ARE DISABLED FOR A LONG PERIOD OF TIME,
  917. SUCH AS THEY ARE DURING SOME ├OMMODORE-╦ERNAL ╔/╧ OPERATIONS.
  918.  
  919. ┴FTER INCREMENTING THE TIME, THE KERNEL CHECKS TO SEE IF ANY ─ELAY()ED
  920. PROCESSES NEED TO BE WOKEN UP.  ╔F THERE ARE NO PROCESSES IN THE DELAY QUEUE,
  921. THEN THIS IS A QUICK CHECK.  ╔F THERE ARE ANY PROCESSES IN THE QUEUE, THEN IF
  922. THE WAKEUP TIME OF THE HEAD PROCESS IS EQUAL TO THE CURRENT TIME, THEN THAT
  923. PROCESS IS WOKEN UP AND THIS CHECK IS PERFORMED REPEATEDLY UNTIL THE CONDITION
  924. FAILS, SINCE THERE MAY BE MULTIPLE PROCESSES THAT WANT TO BE WOKEN UP AT THE
  925. SAME JIFFY OF ABSOLUTE TIME.  ╬OTE THAT BECAUSE OF THE SCHEDULING FOR A
  926. FRESHLY UNBLOCKED PROCESS, THE PROCESS THAT ─ELAY()ED FIRST WILL BE THE
  927. FIRST ONE ACTIVATED AFTER IT IS WOKEN UP, IF THERE ARE MULTIPLE PROCESSES
  928. WOKEN UP AT THE START OF THE SAME JIFFY.
  929.  
  930. 3.6. ╙┘╙╘┼═ ┬╧╧╘╙╘╥┴╨╨╔╬╟
  931.  
  932. ╧PERATING SYSTEMS ALWAYS HAVE A BOOTSTRAPPING PROBLEM, BECAUSE YOU ALWAYS NEED
  933. TO USE THE SERVICES OF THE OPERATING SYSTEM IN ORDER TO START IT UP, BUT, OF
  934. COURSE, IT'S NOT STARTED UP YET, CHICKEN AND EGG, CATCH-22.  ╙O, WHAT USUALLY
  935. ENDS UP HAPPENING IS THAT YOU JUST "FAKE IT", START FROM SOMEWHERE, GET THE
  936. BALL ROLLING, AND SNOWBALL UP TO A FULLY RUNNING SYSTEM.
  937.  
  938. ╘HE FIRST THING THAT THE KERNEL DOES IS CHANGE ALL OF THE INTERRUPT VECTORS
  939. (╔╥╤, ╬═╔, AND ┬╥╦) TO MY CUSTOM ROUTINES.  ╔ NEED TO COVER ALL OF THE
  940. INTERRUPTS, SINCE ╔ CHAVE THE ZERO PAGE DURING THE EXECUTION OF THE SYSTEM,
  941. AND IF A ┬╥╦ OR ╬═╔ WERE TO HAPPEN AND BE SERVICED BY THE ├OMMODORE-╦ERNAL ╥╧═
  942. ROUTINES, ALL HELL WOULD BREAK LOOSE.  ├URRENTLY, THE ╬═╔ AND ┬╥╦ ROUTINES
  943. JUST CLEAN THINGS UP AND RETURN TO ┬┴╙╔├.
  944.  
  945. ╘HEN WE INITIALIZE THE KERNEL VARIABLES, INCLUDING THE DELAY QUEUE AND THE
  946. JIFFY COUNTER.
  947.  
  948. ┴ND THEN WE FAKE THE CREATION OF THE ╬ULL PROCESS.  ╞OR THE PURPOSES OF
  949. BOOTSTRAPPING, THE ╬ULL PROCESS DOUBLES AS THE "┬OOT" PROCESS.  ╔TS PROCESS
  950. CONTROL BLOCK IS NOT ALLOCATED IN THE NORMAL WAY, EITHER; IT IS AT A FIXED
  951. LOCATION, AND ITS ╨├┬ DOUBLES AS THE HEAD OF THE PROCESS LIST.  ┴ KLUGE HERE
  952. AND A HACK THERE AND THE ╬ULL PROCESS IS INITIALIZED AND "JOINED IN
  953. PROGRESS".  ╘HEN, THE ╬ULL PROCESS CREATES THE ╔NIT PROCESS, USING A STANDARD
  954. CALL TO THE ├REATE() PRIMITIVE, AND THEN THE ╬ULL PROCESS GOES INTO AN ENDLESS
  955. LOOP OF INCREMENTING THE 32-BIT VALUE AT ADDRESSES $400-$403, THE FIRST FOUR
  956. LOCATIONS OF THE 40-COLUMN SCREEN MEMORY.  ╔T DOESN'T MATTER WHETHER YOU RUN
  957. ┬╧╙ WITH THE CLOCK IN ╞AST OR ╙LOW MODE, EXCEPT IN TERMS OF PERFORMANCE.
  958.  
  959. ╔T IS THE RESPONSIBILITY OF THE ╔NIT PROCESS TO START UP ALL OF THE USER
  960. PROCESSES IN THE USER APPLICATION AFTER ╔NIT STARTS RUNNING.  ╔N THE CURRENT
  961. IMPLEMENTATION, ╔NIT STARTS UP ALL OF THE OTHER PROCESSES IN THE TEST
  962. APPLICATION AND THEN BECOMES THE ├OMMODORE-╦ERNAL ╙ERVER, WHICH IS A
  963. CONVENIENT ORGANIZATION, SINCE ALL OF THE OTHER PROCESSES CAN FIND OUT THE PID
  964. OF THE ╦ERNAL ╙ERVER MERELY BY CALLING ═Y╨ARENT╨ID().
  965.  
  966. 4. ╔╬╘┼╥╨╥╧├┼╙╙ ├╧══╒╬╔├┴╘╔╧╬
  967.  
  968. ╔N THIS SYSTEM, PROCESSES ARE NOT STRICTLY INDEPENDENT AND COMPETITIVE; MANY
  969. MUST COOPERATE AND COMUNICATE TO GET WORK DONE.  ╘O FACILITIATE THIS
  970. INTERPROCESS COMMUNICATION (╔╨├), A PARTICULAR PARADIGM WAS CHOSEN: THE ╥EMOTE
  971. ╨ROCEDURE ├ALL (╥╨├) PARADIGM.  ╥╨├ IS A MESSAGE-PASSING SCHEME THAT IS USED
  972. WITH THE MUCH-HYPED ├LIENT/╙ERVER SYSTEM-ARCHITECTURE MODEL.  ╔TS OPERATION
  973. PARALLELS THE IMPLICIT OPERATIONS THAT TAKE PLACE WHEN YOU CALL A LOCAL
  974. PROCEDURE (A SUBROUTINE).
  975.  
  976. ╘HE ╥╨├ MESSAGE-PASSING PARADIGM IS ALSO COUPLED WITH A SHARED-MEMORY PARADIGM
  977. TO OFFER GREATER PERFORMANCE FOR PASSING AROUND MASSIVE AMOUNTS OF DATA.  ┴LL
  978. PROCESSES IN THE SYSTEM (AND IN THE ENTIRE DISTRIBUTED SYSTEM WHEN THIS ╧╙ IS
  979. EXTENDED) HAVE GLOBAL ACCESS TO ALL OF THE MEMORY IN THE SYSTEM.  ╘HE COUPLING
  980. OF THE TWO PARADIGMS IS SUCH THAT YOU GET THE BEST OF BOTH WORLDS: THE
  981. CONVENENCE AND NATURAL INTERPROCESS *COORDINATION* (SYNCHRONIZATION) SEMANTICS
  982. OF ╥╨├ AND THE CONVENIENCE AND RAW PERFORMANCE OF SHARED STORAGE.
  983.  
  984. 4.1. ═┼╙╙┴╟┼-╨┴╙╙╔╬╟ ├┴╠╠╙
  985.  
  986. ╘HE KERNEL PROVIDES THREE PRIMITIVES FOR MESSAGE PASSING:
  987.  
  988. ├┴╠╠ ╬┴═┼     ╔╬╨╒╘ ┴╥╟╒═┼╬╘╙                  ╥┼╘╒╥╬ ╓┴╠╒┼╙
  989. -----------   ------------------------------   -------------------------------
  990. ╙END          ( .┴┘=MSG╚EAD )                  .├╙=ERR(.┴=ERRCODE)
  991. ╥ECEIVE       ( .┴┘=MSG╚EAD )                  .┴┘=SENDER╨ID
  992. ╥EPLY         ( .┴┘=MSG╚EAD[MSG╥ET,MSG─ATA] )  .├╙=ERR(.┴=ERRCODE)
  993.  
  994. ╘HESE CALLS WILL SEND A MESSAGE FROM ONE PROCESS (THE CLIENT) TO ANOTHER
  995. PROCESS (THE SERVER) AND WAIT FOR A REPLY, RECEIVE A MESSAGE FROM ANOTHER
  996. PROCESS (A CLIENT), AND REPLY TO A MESSAGE SENT FROM ANOTHER PROCESS (A
  997. CLIENT) THAT HAS BEEN RECEIVED, RESPECTIVELY.
  998.  
  999. 4.1.1. ═┼╙╙┴╟┼-╚┼┴─┼╥ ─┴╘┴ ╙╘╥╒├╘╒╥┼
  1000.  
  1001. ┼ACH OF THE MESSAGE-PASSING PRIMITIVES REQUIRES A POINTER TO A MESSAGE-HEADER
  1002. DATA STRUCTURE THAT IS STORED IN THE USER PROGRAM'S DATA SPACE.  ╘HE MESSAGE
  1003. HEADER MUST BE INITIALIZED WITH APPROPRIATE VALUES BEFORE A MESSAGE CAN BE
  1004. SENT.  ╬OTE THAT THIS SCHEME OF PASSING A POINTER TO A MESSAGE HEADER ALLOWS
  1005. YOU TO HAVE MULTIPLE MESSAGE HEADERS LYING AROUND, INITIALIZED AND READY FOR
  1006. ACTION, AND YOU CAN EASILY PICK BETWEEN THEM.  ╚ERE IS WHAT A MESSAGE HEADER
  1007. LOOKS LIKE:
  1008.  
  1009. ╧╞╞   ╙╔┌   ├╠┴╙╙   ╠┴┬┼╠
  1010. ---   ---   -----   ------
  1011.   0     2   PID     MSG╘O
  1012.   2     2   PID     MSG╞ROM
  1013.   4     4   BUF     MSG┬UF
  1014.   8     2   BUF     MSG╠EN
  1015.  10     4   BUF     MSG╥EP┬UF
  1016.  14     2   BUF     MSG╥EP╠EN
  1017.  16     1   DATA    MSG╧P
  1018.  17     1   DATA    MSG╥ET
  1019.  18     2   DATA    MSG╧BJ
  1020.  20     4   DATA    MSG─ATA
  1021.  24     -   -       ╙╔┌┼
  1022.  
  1023. ┘OU SHOULD NOT PUT TOO MUCH FAITH IN THE OFFSETS OF THE FIELDS IN THE DATA
  1024. STRUCTURE REMAINING STATIC; YOU SHOULD ALWAYS USE THE LABEL TO ACCESS THE
  1025. FIELDS OF THE STRUCTURE, AS IN:
  1026.  
  1027. STA MY═ESSAGE╚EADER+MSG╘O+0
  1028. STY MY═ESSAGE╚EADER+MSG╘O+1
  1029.  
  1030. 4.1.1.1. ╨╔─-├╠┴╙╙ ╞╔┼╠─╙
  1031.  
  1032. ╘HE FIRST TWO FIELDS, OF CLASS "PID", ARE USED TO IDENTIFY THE PROCESSES
  1033. INVOLVED IN AN ╥╨├ INTERACTION.  ╘HE "MSG╘O" FIELD IS THE PID OF THE PROCESS
  1034. THAT A MESSAGE IS TO BE/HAS BEEN SENT TO, AND THE "PCB╞ROM" FIELD IS THE ID OF
  1035. THE PROCESS WHICH A MESSAGE HAS BEEN RECEIVED FROM.  ╞OR SECURITY REASONS, THE
  1036. SENDER DOES NOT FILL IN THE "PCB╞ROM" FIELD; THE KERNEL DOES AFTER THE MESSAGE
  1037. HAS BEEN SENT AND THE SENDER IS BLOCKED.  (╧R ELSE THE SENDER COULD FAKE BEING
  1038. SOMEONE ELSE).  ╘HE "PCB╘O" FIELD IS USED AS THE DESTINATION FOR WHEN A
  1039. MESSAGE IS BEING SENT AND MUST BE FILLED IN WITH A LEGITIMATE VALUE ON A SEND
  1040. OPERATION, AND THE "PCB╞ROM" FIELD IS USED AS THE DESTINATION WHEN A MESSAGE
  1041. IS BEING REPLIED TO, AND MUST BE FILLED IN WITH A LEGITIMATE VALUE ON A REPLY
  1042. OPERATION.  ╘HE "PCB╘O" FIELD IS THE ONLY FIELD OF THE MESSAGE HEADER THAT
  1043. ACTUALLY NEEDS TO HAVE A LEGITIMATE VALUE BEFORE A MESSAGE CAN BE SENT.
  1044.  
  1045. 4.1.1.1. ┬╒╞-├╠┴╙╙ ╞╔┼╠─╙
  1046.  
  1047. ╘HE NEXT FOUR FIELDS, OF CLASS "BUF", POINT OUT THE SEND AND REPLY BUFFERS IN
  1048. MEMORY AND THE SIZES OF EACH.  ╘HE SEND BUFFER ("MSG┬UF"/"MSG╠EN") IS EXPECTED
  1049. TO POINT TO A REGION OF NEAR/FAR MEMORY THAT CONTAINS VALID DATA FOR A SEND
  1050. OPERATION, AND THE REPLY BUFFER ("MSG╥EP┬UF"/"MSG╥EP╠EN") IS EXPECTED TO POINT
  1051. TO A VALID AREA OF MEMORY FOR THE SERVER TO FILL IN WITH ANY BULKY RESULT DATA
  1052. FROM AN ╥╨├ REQUEST.  ┼ACH OF THE MESSAGE-BUFFER POINTERS IS FOUR BYTES IN
  1053. SIZE TO ALLOW FOR FUTURE EXPANSION WHEN THE KERNEL WILL SUPPORT "FAR" MEMORY
  1054. THAT WILL BE ACCESSED THROUGH 32-BIT POINTERS.  ╒SER PROCESSES ARE EXPECTED TO
  1055. ACCESS THESE "FAR" BUFFERS DIRECTLY THEMSELVES, THROUGH THE GLOBAL SHARED
  1056. MEMORY.  ╘HIS ELIMINATES THE SYSTEM OVERHEAD OF USELESSLY COPYING BULKY DATA
  1057. FROM PLACE TO PLACE.
  1058.  
  1059. ╘HERE ARE TWO SPECIAL NOTES TO MAKE ABOUT THERE "BUF" FIELDS.  ╞IRST, THEY
  1060. DON'T ACTUALLY HAVE TO BE USED HOW THEY'RE INTENDED TO BE USED. AS LONG AS
  1061. BOTH THE CLIENT AND THE SERVER AGREE ON WHAT THE CONTENTS OF THESE FIELDS ARE
  1062. SUPPOSED TO MEAN.  ╔N THIS RESPECT, THE FIELDS CAN BE USED TO QUICKLY PASS
  1063. TWELVE BYTES OF COMPLETELY ARBITRARY INFORMATION.  ╘HIS IS USEFUL BECAUSE MANY
  1064. ╥╨├S ONLY REQUIRE THAT A SMALL AMOUNT OF INFORMATION BE TRANSFERRED FROM ONE
  1065. PROCESS TO ANOTHER, OR AT LEAST THAT BULKY DATA BE PASSED IN ONLY ONE
  1066. DIRECTION (LIKE READ OR WRITE), SO THAT ONE OF THE BUFFER POINTERS IS FREE TO
  1067. BE USED QUICK, TINY DATA.
  1068.  
  1069. ╙ECOND, ON THE SENDING SIDE, THE "BUFFER" THAT IS POINTED TO DOES NOT HAVE TO
  1070. BE A "BUFFER" AT ALL; IT CAN BE AN ARBITRARY DATA STRUCTURE THAT HAS AN
  1071. ARBITRARY NUMBER OF PIECES, SCATTERED THROUGHOUT THE GLOBAL MEMORY OF THE
  1072. SYSTEM.  ╘HE ONLY RESPONSIBILITY OF THE SENDER IS TO INSURE THAT NO ONE ELSE
  1073. WILL BE ATTEMPTING TO MODIFY THE SHARED DATA SIMULTANEOUSLY WHILE THE SERVER
  1074. IS ACCESSING IT.  ╘HIS SCHEME IS QUITE INGENIOUS, ╔ THINK (THANK YOU, THANK
  1075. YOU).  (╘HE SCHEME MAY APPEAR TO HAVE A SECURITY LEAK IN THE DESIGN, BUT OUR
  1076. SYSTEM HAS NO REAL HARDWARE SECURITY ANYWAY).
  1077.  
  1078. ╘HE EXPECTED USAGE OF BUFFERS WILL BE FOR THE SENDER TO USE NEAR MEMORY FOR
  1079. THE REQUEST AND REPLY BUFFERS AND ACCESS THEM AS REGULAR NEAR MEMORY TO
  1080. CONSTRUCT AND INTERPRET REQUEST AND REPLY MESSAGES.  ╘HE RECEIVER WILL (IN THE
  1081. FUTURE) ACCESS THE BUFFERS AS FAR MEMORY (WHICH THEY MAY VERY WELL BE SINCE
  1082. PROCESSES WILL BE ALLOWED TO EXECUTE ON DIFFERENT BANKS OF INTERNAL MEMORY AND
  1083. EVEN ON DIFFERENT MACHINES), AND MAY WISH TO FETCH PARTS OF MESSAGES INTO NEAR
  1084. MEMORY FOR PROCESSING.  ╘HE USE OF FAR POINTERS MAKES IT SO THAT DATA IS
  1085. COPIED ONLY WHEN NECESSARY, AND COPIED ONLY ONCE.
  1086.  
  1087. 4.1.1.3. ─┴╘┴-├╠┴╙╙ ╞╔┼╠─╙
  1088.  
  1089. ╘HE FINAL FOUR FIELDS, OF CLASS "DATA", ARE INTENDED TO BE USED TO
  1090. CONVENIENTLY PASS SMALL AMOUNTS OF ARBITRARY DATA.  ╘HIS DATA CAN BE
  1091. ARBITRARY, BUT THE FIELDS DO HAVE A CONVENTION THAT SHOULD USUALLY BE
  1092. FOLLOWED, UNLESS BOTH PARTIES AGREE TO AN ALTERNATIVE USAGE.
  1093.  
  1094. ╘HE "MSG╧P" FIELD IS INTENDED TO BE THE "OPERATION CODE" THAT A CLIENT PROCESS
  1095. WISHES A SERVER TO EXECUTE.  ╘HE "MSG╥ET" FIELD IS INTENDED TO BE THE RETURN/
  1096. ERROR CODE THAT IS RETURNED FROM THE SERVER TO THE CLIENT UPON COMPLETION OF
  1097. AN OPERATION.  ╘HE "MSG╧BJ" FIELD IS INTENDED TO BE USED BY THE CLIENT TO
  1098. INDICATE WHICH OF THE SERVER'S "OBJECTS" THE CLIENT WISHES TO PERFORM THE
  1099. OPERATION ON.  ┴ND THE "MSG─ATA" FIELD IS INTENDED TO CONTAIN FOUR BYTES OF
  1100. ARBITRARY USER DATA THAT IS PASSED IN WITH AN OPERATION AND IS PASSED BACK
  1101. FROM THE SERVER TO GIVE RETURN VALUES.  ╔N THE SPIRIT OF THESE SEMANTICS, THE
  1102. DATA IN ALL OF THE FIELDS IS SEND WITH A REQUEST, BUT ONLY THE DATA IN THE
  1103. "MSG╥ET" AND "MSG─ATA" FIELDS IS PASSED BACK IN A REPLY OPERATION.  ╬ONE OF
  1104. THE OTHER FIELDS ARE PASSED BACK IN A REPLY OPERATION (THE FIELD VALUES WILL
  1105. REMAIN HOW THEY WERE BEFORE THE SEND, FOR THE SENDER).  ╘AKE SPECIAL NOTE THAT
  1106. THE "MSG╥EP╠EN" FIELD WILL NOT BE PASSED BACK; IF THERE IS LESS DATA RETURNED
  1107. THAN WAS ASKED FOR BY AN OPERATION, YOU WILL HAVE TO ENCODE THE "ACTUAL"
  1108. REPLY-BUFFER LENGTH INTO THE "MSG─ATA" FIELD.
  1109.  
  1110. 4.1.2. ╙┼╬─
  1111.  
  1112. ╙END() IS USED TO TRANSMIT A MESSAGE TO A REMOTE PROCESS AND GET BACK A REPLY
  1113. MESSAGE.  ╘HE .┴┘ REGISTER CONTAINS THE NEAR-MEMORY ADDRESS OF THE MESSAGE
  1114. HEADER, WHICH MUST HAVE ITS "MSG╘O" FIELD FILLED IN TO BE THE PID OF THE
  1115. PROCESS THAT THE MESSAGE IS BEING SENT TO.  ╘HE SENDING PROCESS WILL SUSPEND
  1116. ITS EXECUTION WHILE IT IS WAITING FOR REMOTE PROCESS TO PROCESS ITS REQUEST.
  1117. ╔F THERE IS TO BE BULKY REPLY DATA FOR THE REQUEST (SUCH AS THERE WOULD BE FOR
  1118. A "READ" REQUEST TO A FILE SERVER), THEN SPACE FOR THE REPLY BUFFER MUST BE
  1119. ALLOCATED AND INDICATED IN THE MESSAGE HEADER.  ╘HE REPLY-BUFFER SPACE SHOULD
  1120. NORMALLY BE OWNED BY THE SENDER.
  1121.  
  1122. ╔F THERE IS AN ERROR IN PASSING THE MESSAGE, THE THE ERROR RETURN WILL BE
  1123. INDICATED BY THE CARRY FLAG BEING SET AND THE ERROR CODE WILL BE RETURNED IN
  1124. THE .┴ REGISTER.  ╙OME POSSIBLE ERRORS WILL BE, IN THE FUTURE:  DESTINATION
  1125. PROCESS IS NOT VALID, AND THAT DESTINATION PROCESS DIED BEFORE RECEIVING/
  1126. REPLYING TO YOUR MESSAGE.  (╘HESE CONDITIONS ARE NOT CURRENTLY CHECKED).  ┴LSO
  1127. IN THE FUTURE, THIS CALL WILL WORK COMPLETELY TRANSPARENTLY FOR PASSING
  1128. MESSAGES BETWEEN MACHINES IN A NETWORK.
  1129.  
  1130. 4.1.3. ╥┼├┼╔╓┼
  1131.  
  1132. ╥ECEIVE() IS USED TO RECEIVE A MESSAGE TRANSMITTED BY A REMOTE PROCESS TO THE
  1133. CURRENT PROCESS.  ╘HE RECEIVER WILL BLOCK UNTIL ANOTHER PROCESS DOES A
  1134. CORRESPONDING ╙END() OPERATION, AND THEN THE MESSAGE HEADER SENT BY THE SENDER
  1135. WILL BE RETRIEVED INTO THE MESSAGE-HEADER BUFFER POINTED TO BY THE .┴┘
  1136. REGISTER, FOR THIS CALL.  ╬O ERROR RETURNS ARE POSSIBLE.  ╘HE PID OF THE
  1137. SENDING PROCESS WILL BE RETURNED IN THE .┴┘ REGISTER AS WELL AS IN THE
  1138. "MSG╞ROM" FIELD OF THE RECEIVE-MESSAGE-HEADER BUFFER.  ╘HE RECEIVER IS THEN
  1139. EXPECTED TO EVENTUALLY CALL THE ╥EPLY() PRIMITIVE TO RE-AWAKEN THE SENDER.
  1140. ╘HE RECEIVER IS FREE TO DO ANYTHING IT WANTS TO AFTER RECEIVING A MESSAGE FROM
  1141. A PROCESS, INCLUDING RECEIVING MESSAGES FROM OTHER PROCESSES.  ═ESSAGES ARE
  1142. RECEIVED FROM OTHER PROCESSES IN ╞╔╞╧ ORDER.
  1143.  
  1144. ┴ SIMILAR ╥ECEIVE╙PECIFIC() PRIMITIVE MAY BE PROVIDED IN THE FUTURE.  ╔T WOULD
  1145. ONLY ACCEPT A MESSAGE FROM A SPECIFICALLY NAMED PROCESS AND WOULD ENQUEUE ALL
  1146. OTHER MESSAGES THAT ARE RECEIVED BEFORE THE SPECIFIC MESSAGE, TO BE RECEIVED
  1147. LATER.
  1148.  
  1149. 4.1.4. ╥┼╨╠┘
  1150.  
  1151. ╥EPLY() IS USED TO RE-AWAKEN A PROCESS THAT SENT A MESSAGE THAT WAS ╥ECEIVE()D
  1152. BY THE CURRENT PROCESS.  ╘HE CURRENT PROCESS IS EXPECTED TO HAVE SET UP THE
  1153. RETURN INFORMATION IN THE REPLY-MESSAGE-HEADER BUFFER AND THE REPLY BUFFER
  1154. AREA ACCORDING TO THE CLIENT'S WISHES BEFORE CALLING THE ╥EPLY() PRIMITIVE.
  1155. ╘HE NEAR ADDRESS OF THE REPLY-MESSAGE-HEADER BUFFER IS LOADED INTO THE .┴┘
  1156. REGISTER AS AN ARGUMENT TO THE CALL.  ╧NLY THE "MSG╞ROM", "MSG╥ET", AND
  1157. "MSG─ATA" FIELDS NEED TO HAVE VALUES.  ╘HE "MSG╞ROM" FIELD IDENTIFIES THE
  1158. PROCESS TO SEND THE REPLY MESSAGE TO, AND THAT PROCESS MUST BE IN THE STATE OF
  1159. WAITING FOR A REPLY FROM THE ╥EPLY()ING PROCESS, OR AN ERROR WILL BE
  1160. RETURNED.  ┴N ERROR IS INDICATED BY THE CARRY FLAG BEING SET ON RETURN AND THE
  1161. ERROR CODE IS LOADED IN THE .┴ REGISTER.  ╔N THE CASE OF AN ERROR, NO ACTION
  1162. WILL HAVE BEEN PERFORMED BY THE SYSTEM.
  1163.  
  1164. 4.2. ╔═╨╠┼═┼╬╘┴╘╔╧╬
  1165.  
  1166. ╘HE FIELDS OF THE PROCESS CONTROL BLOCK THAT ARE USED FOR MESSAGE PASSING
  1167. ARE RESTATED HERE:
  1168.  
  1169. ╧╞╞   ╙╔┌   ├╠┴╙╙   ╠┴┬┼╠
  1170. ---   ---   -----   ------
  1171.  12     2   IPC     PCB╙END═SG╨TR  (OVERLAP)
  1172.  12     2   IPC     PCB╥ECV═SG╨TR  (OVERLAP)
  1173.  14     2   IPC/Q   PCB╙END╤╚EAD
  1174.  16     2   IPC/Q   PCB╙END╤╘AIL
  1175.  18     1   IPC/Q   PCB╙END╤╞LAG
  1176.  19     1   IPC/Q   PCB╙END╤├OUNT
  1177.  20     2   IPC     PCB┬LOCKED╧N
  1178.  22     2   IPC     PCB╥ECEIVE╞ROM
  1179.  
  1180. ╘HE "PCB┬LOCKED╧N" FIELD IS USED TO ALLOW ╥EPLY() TO VERIFY THAT THE PID IT IS
  1181. INSTRUCTED TO SEND A REPLY MESSAGE TO IS INDEED WAITING FOR A REPLY FROM THE
  1182. TASK CALLING ╥EPLY().  ╘HE "PCB╙END╤*" FIELDS CONSTITUTE A QUEUE HEAD FOR A
  1183. LIST OF PROCESS CONTROL BLOCKS THAT ARE WAITING TO SEND A MESSAGE TO THE
  1184. CURRENT PROCESS.  ╘HE "PCB╙END═SG╨TR" AND "PCB╥ECV═SG╨TR" FIELDS ARE USED TO
  1185. SAVE THE MESSAGE DATA PARAMETERS OF A ╙END() OR ╥ECEIVE() CALL, RESPECTIVELY,
  1186. WHEN IT HAS TO BE SUSPENDED WITHOUT A TRANSFER OF THE MESSAGE HEADER.  ╫HEN
  1187. THE OTHER PROCESS INVOLVED PERFORMS THE CORRESPONDING OPERATION, THE FIRST
  1188. PROCESS' HEADER BUFFER POINTER IS RECOVERED FROM ITS PROCESS CONTROL BLOCK.
  1189. ╘HE "PCB╥ECEIVE╞ROM" FIELD IS UNUSED AT THIS TIME.
  1190.  
  1191. ╘HE PROCESS STATES OF ╙╘┴╘┼_╙┼╬─, ╙╘┴╘┼_╥┼╨╠┘, AND ╙╘┴╘┼_╥┼├┼╔╓┼ ARE USED WITH
  1192. MESSAGE PASSING.  ╘HE ╙╘┴╘┼_╙┼╬─ STATE MEANS THAT THE CURRENT PROCESS HAS SENT
  1193. A MESSAGE TO A SERVER PROCESS AND IS WAITING FOR IT TO DO A ╥ECEIVE().  ╘HE
  1194. ╙╘┴╘┼_╥┼╨╠┘ STATE MEANS THAT THE CURRENT PROCESS HAS SENT A MESSAGE TO A
  1195. SERVER PROCESS, THE MESSAGE HAS BEEN ╥ECEIVE()D, AND THAT THE CURRENT PROCESS
  1196. IS WAITING FOR THE SERVER PROCESS TO PERFORM A ╥EPLY().  ╘HE ╙╘┴╘┼_╥┼├┼╔╓┼
  1197. STATE MEANS THAT THE CURRENT PROCESS HAS PERFORMED A ╥ECEIVE() AND IS WAITING
  1198. FOR SOME OTHER PROCESS TO PERFORM A CORRESPONDING ╙END().  ╘HESE STATE
  1199. NAMES/MEANINGS MAY BE A BIT INCONSISTENT; DEAL WITH IT.
  1200.  
  1201. ╘HE IMPLEMENTATION OF THE ACTUAL ╙END(), ╥ECEIVE(), AND ╥EPLY() OPERATIONS IS
  1202. ACTUALLY QUITE STRAIGHT-FORWARD.  ┬OTH ╙END() AND ╥ECEIVE() HAVE TO HANDLE TWO
  1203. POSSIBILE SITUATIONS: EITHER THE OTHER PROCESS INVOLVED HAS ALREADY PERFORMED
  1204. ITS CORRESPONDING OPERATION AND IS WAITING, OR IT HAS NOT.  ╥EPLY() IS
  1205. SIMPLIFIED IN THAT IT KNOWS THAT THE SENDER IS ALREADY WAITING FOR ITS REPLY
  1206. SO IT CAN PROCEED TO COPY THE REPLY-MESSAGE-HEADER CONTENTS DIRECTLY.
  1207.  
  1208. ╘HE ╙END() PRIMITIVE (WILL) CHECKS THE GIVEN DESTINATION PID FOR VALIDITY AND
  1209. THEN CHECKS THE STATE OF THE RECIPIENT PROCESS.  ╔F THE RECIPIENT PROCESS IS
  1210. IN ╙╘┴╘┼_╥┼├┼╔╓┼, THE ╙END() FUNCTION COPIES THE MESSAGE-HEADER CONTENTS
  1211. DIRECTLY TO THE RECEIVE-HEADER BUFFER OF THE RECIPIENT.  ╘HE ADDRESS OF THE
  1212. RECEIVE-HEADER BUFFER IS TAKEN FROM THE "PCB╥ECV═SG╨TR" FIELD OF THE
  1213. RECEIVER'S PROCESS CONTROL BLOCK IN THIS CASE.  ╘HE RECEIVER'S RETURN VALUE
  1214. (THE SENDING PROCESS' PID) IS SET UP (ON THE RECEIVING PROCESS' STACK) AND THE
  1215. RECEIVER IS AWAKENED WHILE THE SENDER IS PUT TO SLEEP, IN ╙╘┴╘┼_╥┼╨╠┘ STATE
  1216. (SINCE THE RECEIVE HAS ALREADY HAPPENED, IT IS WAITING FOR THE CORRESPONDING
  1217. ╥EPLY()).
  1218.  
  1219. ╔F THE RECIPIENT PROCESS IS NOT IN THE ╙╘┴╘┼_╥┼├┼╔╓┼ STATE, THEN THE SENDING
  1220. PROCESS WILL HAVE TO WAIT FOR THE RECIPIENT TO PERFORM A ╥ECEIVE().  ╘HE
  1221. SENDER'S MESSAGE-HEADER BUFFER ADDRESS IS STORED INTO ITS PROCESS CONTROL
  1222. BLOCK, THE SENDER'S PROCESS CONTROL BLOCK IS LINKED INTO THE RECIPIENT
  1223. PROCESS' "PCB╙END╤*", AND THE SENDER IS PUT TO SLEEP, IN THE ╙╘┴╘┼_╙┼╬─
  1224. STATE.
  1225.  
  1226. ╘HE ╙END() FUNCTION DOES NOT SET UP THE RETURN VALUE FOR THE USER'S
  1227. SYSTEM CALL SINCE THAT WILL NOT BE KNOWN UNTIL ANOTHER PROCESS PERFORMS THE
  1228. CORRESPONDING ╥EPLY().  ┴ RETURN VALUE IS SET UP IMMEDIATELY ONLY IN THE CASE
  1229. OF AN ERROR.  ╘HE POSSIBLE ERROR RETURNS FROM ╙END() ARE: INVALID PID AND
  1230. REPLY TOO LONG (IN WHICH CASE THE REPLY IS TRUNCATED).
  1231.  
  1232. ╘HE ╥ECEIVE() PRIMITIVE FIRST CHECKS ITS "PCB╙END╤*" TO SEE IF ANY PROCESSES
  1233. HAVE ALREADY TRIED TO SEND A MESSAGE TO THE RECEIVER.  ╔F THERE IS A PROCESS
  1234. THERE, THE SENDER'S PROCESS CONTROL BLOCK IS REMOVED FROM THE HEAD OF THE SEND
  1235. QUEUE THEN THE SENDER PROCESS' STATE IS CHANGED TO ╙╘┴╘┼_╥┼╨╠┘ AND THE SENT
  1236. MESSAGE-HEADER CONTENTS (DEREFERENCED BY THE SENDER'S "PCB╙END═SG╨TR" POINTER)
  1237. ARE COPIED INTO THE RECEIVER'S MESSAGE-HEADER BUFFER.  ╘HE ╥ECEIVE() PRIMITIVE
  1238. THEN EXITS RETURNING THE PID OF THE SENDER.  ╬O ERROR RETURNS ARE POSSIBLE.
  1239.  
  1240. ╔F THERE IS NO PROCESS ENQUEUED IN THE RECIPIENT PROCESS' "PCB╙END╤*", THEN
  1241. THE RECEIVING PROCESS IS PUT TO SLEEP IN THE ╙╘┴╘┼_╥┼├┼╔╓┼ STATE AND ITS
  1242. MESSAGE-HEADER BUFFER POINTER IS COPIED INTO ITS PROCESS CONTROL BLOCK.
  1243.  
  1244. ╘HE ╥EPLY() PRIMITIVE VERIFIES THAT THE DESTINATION PROCESS IS VALID (BUT NOT
  1245. IN THE CURRENT IMPLEMENTATION) AND IS ACTUALLY AWAITING A REPLY FROM THE
  1246. REPLYING PROCESS.  ╔F NOT, IT CRAPS OUT.  ╧THERWISE, IT COPIES THE TWO
  1247. MESSAGE-HEADER FIELDS AND AWAKENS THE SENDER.  ╘HE RETURN VALUE OF THE SENDER
  1248. IS (ALREADY) SET UP TO BE CARRY-CLEAR (NO ERROR) AND THE ╥EPLY() PRIMITIVE
  1249. RETURNS ERROR-FREE TOO.
  1250.  
  1251. ╘HE ┼XIT() KERNEL CALL DOES NOT CURRENTLY RECOVER FROM A PROCESS PERFORMING A
  1252. ╥ECEIVE() AND THEN ┼XIT()ING BEFORE PERFORMING THE CORRESPONDING ╥EPLY().
  1253. ╙OME CARE WILL HAVE TO BE TAKEN TO INSURE THAT ALL PROCESS INVOLVED IN ╔╨├ CAN
  1254. CONSISTENTLY RECOVER IF ONE OF THE PROCESSES GETS BLOWN AWAY, FOR WHATEVER
  1255. REASON (INCLUDING ┼XIT()).  ╙UCH CONSISTENT RECOVERY HAS TO BE CAREFULLY
  1256. THOUGHT OUT FOR ANY KIND OF OPERATING SYSTEM; HOWEVER, SINCE THERE ARE ONLY A
  1257. SMALL NUMBER OF KERNEL CONCEPTS IN THIS ONE, CONSISTENT RECOVERY IS THAT MUCH
  1258. EASIER TO INSURE.
  1259.  
  1260. 5. ├╧╬├╠╒╙╔╧╬
  1261.  
  1262. ╙O THERE YA HAVE IT; THE START OF A REAL OPERATING SYSTEM FOR THE ├OMMODORE
  1263. 128.  ╫HAT THE OPERATING SYSTEM NEEDS IN TERMS OF FEATURES IS TO BE EXTENDED
  1264. TO EXECUTE PROCESSES ON ANY BANK OF INTERNAL MEMORY, TO ACCESS FAR MEMORY, AND
  1265. TO BE DISTRIBUTED SO THAT IT WILL WORK ACROSS MULTIPLE HOSTS.  ╫HAT IT NEEDS
  1266. IN TERMS OF SOFTWARE IS: DEVICE DRIVERS, A COMMAND SHELL, UTILITY PROGRAMS,
  1267. AND AN ASSEMBLER THAT CAN PRODUCE RELOCATABLE CODE.  ╧H WHERE, OH WHERE SHALL
  1268. ╔ EVER FIND SUCH SOFTWARE???  ;-)
  1269. ------------------------------------------------------------------------------
  1270. ┴╨╨┼╬─╔╪ ┴. ╙╧╒╥├┼-├╧─┼ ╠╔╙╘╔╬╟
  1271.  
  1272. ╘HE SOURCE CODE FOLLOWS.  ┼XTRACT EVERYTHING BETWEEN THE "-----=-----" LINES
  1273. AND SAVE INTO A FILE NAMED "BOS.S" (OR WHATEVER) AND THEN RUN IT THROUGH THE
  1274. ┴├┼ ASSEMBLER TO GENERATE THE EXECUTABLE PROGRAM (WHICH IS ALSO INCLUDED BELOW
  1275. FOR YOUR CONVENIENCE).  ╘HE ┴├┼ ASSEMBLER IS AVAILABLE FOR FREE WITH THE
  1276. ┴├┼-128/64 SYSTEM.
  1277.  
  1278. ╔ HAVE NOT GONE THROUGH AND FULLY DOCUMENTED THE SOURCE CODE, SINCE ╔ HAVE
  1279. BEEN SITTING ON THIS PROGRAM FOR QUITE A WHILE AND AM IN A RUSH TO GET IT OUT
  1280. THE DOOR.  ┬ESIDES, THE FUNCTIONALITY OF EACH IMPORTANT COMPONENT HAS ALREADY
  1281. BEEN DISCUSSED.
  1282.  
  1283. -----=-----
  1284. ;SIMPLE MULTITASKING KERNEL BY ├RAIG ┬RUCE, STARTED 25-╧CT-1994.
  1285.  
  1286. ;╘HIS PROGRAM IS WRITTEN IN THE ┴├┼-┴SSEMBLER FORMAT.
  1287.  
  1288.    ORG $1300
  1289.    JMP MAIN
  1290.  
  1291. ;======== DECLARATIONS ========
  1292.  
  1293. PCB╬EXT         = 00 ;(2) MGMT
  1294. PCB╨REV         = 02 ;(2) MGMT
  1295. PCB╔S╚EAD       = 04 ;(1) MGMT
  1296. PCB╤├OUNT       = 05 ;(1) MGMT
  1297. PCB╙╨           = 06 ;(1) CTXT
  1298. PCB╙TACK╨AGE    = 07 ;(1) CTXT
  1299. PCB┌ERO╨AGE     = 08 ;(1) CTXT
  1300. PCB─506         = 09 ;(1) CTXT
  1301. PCB╨RIORITY     = 10 ;(1) SCHE
  1302. PCB├OUNTDOWN    = 11 ;(1) SCHE
  1303. PCB╫AKEUP╘IME   = 12 ;(2) SCHE (OVERLAP)
  1304. PCB╫AIT┼VENT    = 12 ;(1) SCHE (OVERLAP)
  1305. PCB╙END═SG╨TR   = 12 ;(2) SCHE (OVERLAP)
  1306. PCB╥ECV═SG╨TR   = 12 ;(2) SCHE (OVERLAP)
  1307. PCB╙END╤╚EAD    = 14 ;(2) IPC
  1308. PCB╙END╤╘AIL    = 16 ;(2) IPC
  1309. PCB╙END╤╞LAG    = 18 ;(1) IPC
  1310. PCB╙END╤├OUNT   = 19 ;(1) IPC
  1311. PCB┬LOCKED╧N    = 20 ;(2) IPC
  1312. PCB╥ECEIVE╞ROM  = 22 ;(2) IPC
  1313. PCB╨ARENT       = 24 ;(2) PROC
  1314. PCB╙TATE        = 26 ;(1) PROC
  1315. PCB╙IZE         = 27
  1316.  
  1317. ╙╘┴╘┼_╥┼┴─┘     = $C0
  1318. ╙╘┴╘┼_╙┼╬─      = $C1
  1319. ╙╘┴╘┼_╥┼├┼╔╓┼   = $C2
  1320. ╙╘┴╘┼_╥┼╨╠┘     = $C3
  1321. ╙╘┴╘┼_─┼╠┴┘     = $C4
  1322. ╙╘┴╘┼_╙╒╙╨┼╬─┼─ = $C5
  1323. ╙╘┴╘┼_┼╓┼╬╘     = $C6
  1324.  
  1325. ╦┼╥╬_┼╥╥_╧╦            = $E0
  1326. ╦┼╥╬_┼╥╥_╨╔─_╬╧╘_╥┼╨╠┘ = $E1
  1327.  
  1328. MSG╘O           =  0 ;(2)
  1329. MSG╞ROM         =  2 ;(2)
  1330. MSG┬UF          =  4 ;(4)
  1331. MSG╠EN          =  8 ;(2)
  1332. MSG╥EP┬UF       = 10 ;(4)
  1333. MSG╥EP╠EN       = 14 ;(2)
  1334. MSG╧P           = 16 ;(1)
  1335. MSG╥ET          = 17 ;(1)
  1336. MSG╧BJ          = 18 ;(2)
  1337. MSG─ATA         = 20 ;(4)
  1338. MSG╙IZE         = 24
  1339.  
  1340. QUEUE╚EAD╙IZE   = 6
  1341.  
  1342. NULL╨CB    : BUF PCB╙IZE
  1343. DELAY╤UEUE : BUF QUEUE╚EAD╙IZE
  1344. JIFFY╘IME  : BUF 2
  1345.  
  1346. ACTIVE╨ID  = 02 ;(2)
  1347. P          = 04 ;(2)
  1348. Q          = 06 ;(2)
  1349. PCB╨TR     = 08 ;(2)
  1350. MSG╨TR     = 10 ;(2)
  1351. PAGE┴LLOC  = 12 ;(1)
  1352.  
  1353. ;╙TACK: ($FF)      : EXITADDR-1.H
  1354. ;       ($FE)      : EXITADDR-1.L
  1355. ;       ($FD) SP+07: PC.H
  1356. ;       ($FC) SP+06: PC.L
  1357. ;       ($FB) SP+05: STATUS REGISTER
  1358. ;       ($FA) SP+04: .┴
  1359. ;       ($F9) SP+03: .╪
  1360. ;       ($F8) SP+02: .┘
  1361. ;       ($F7) SP+01: $FF00 SAVE
  1362. ;       ($F6) SP+00: -EMPTY-
  1363.  
  1364. BK┬╧╙    = $0E
  1365. BK╒SER   = $0E
  1366. BK╙ELECT = $FF00
  1367. VIC      = $D000
  1368. SID      = $D400
  1369. MMU┌ERO╨AGE  = $D507
  1370. MMU╙TACK╨AGE = $D509
  1371. ╔RQ┼XIT  = $FF33
  1372.  
  1373. ; ├REATE  ( .┴┘=ADDRESS, .╪=PRIORITY ) : .┴┘=PID
  1374. ; ┼XIT    ( .┴=CODE, .╪=$00 )
  1375. ; ═Y╨ID   ( ) : .┴┘=PID
  1376. ; ═Y╨ARENT╨ID ( ) : .┴┘=PARENT╨ID
  1377. ; ╙USPEND ( )
  1378. ; ─ELAY   ( .┴┘=JIFFIES ) : .├╙=ERR
  1379. ; ╙END    ( .┴┘=MSG┬UF ) : .├╙:.┴=ERR
  1380. ; ╥ECEIVE ( .┴┘=MSG┬UF ) : .┴┘=SENDER╨ID
  1381. ; ╥EPLY   ( .┴┘=MSG┬UF[MSG╥ET,MSG─ATA] ) : .├╙:.┴=ERR
  1382.  
  1383. ;======== KERNEL CODE ========
  1384.  
  1385. MAIN = *
  1386.    SEI
  1387.    ;** ENTRY
  1388.    LDA #BK┬╧╙
  1389.    STA BK╙ELECT
  1390.    ;** SET INTERRUPT VECTORS
  1391.    LDA #<╔RQ╚ANDLER
  1392.    LDY #>╔RQ╚ANDLER
  1393.    STA $0314
  1394.    STY $0315
  1395.    LDA #<┬RK╚ANDLER
  1396.    LDY #>┬RK╚ANDLER
  1397.    STA $0316
  1398.    STY $0317
  1399.    LDA #<╬MI╚ANDLER
  1400.    LDY #>╬MI╚ANDLER
  1401.    STA $0318
  1402.    STY $0319
  1403.    ;** INITIALIZE DELAY QUEUE
  1404.    LDA #0
  1405.    STA JIFFY╘IME+0
  1406.    STA JIFFY╘IME+1
  1407.    LDA #<DELAY╤UEUE
  1408.    LDY #>DELAY╤UEUE
  1409.    STA Q+0
  1410.    STY Q+1
  1411.    JSR ╤UEUE╔NIT
  1412.    ;** INITIALIZE NULL/BOOT PROCESS
  1413.    LDA #<NULL╨CB
  1414.    LDY #>NULL╨CB
  1415.    STA NULL╨CB+PCB╬EXT+0
  1416.    STY NULL╨CB+PCB╬EXT+1
  1417.    STA NULL╨CB+PCB╨REV+0
  1418.    STY NULL╨CB+PCB╨REV+1
  1419.    STA ACTIVE╨ID+0
  1420.    STY ACTIVE╨ID+1
  1421.    LDA #$FF
  1422.    STA NULL╨CB+PCB╔S╚EAD
  1423.    LDA #0
  1424.    STA NULL╨CB+PCB╤├OUNT
  1425.    LDA #>$2000
  1426.    STA PAGE┴LLOC
  1427.    LDA #╙╘┴╘┼_╥┼┴─┘
  1428.    STA NULL╨CB+PCB╙TATE
  1429.    LDA #2
  1430.    STA NULL╨CB+PCB╨RIORITY
  1431.    CLI
  1432.    JMP ╬ULL
  1433.  
  1434. ╬ULL = *
  1435.    ;** CREATE INIT PROCESS
  1436.    LDA #<╔NIT
  1437.    LDY #>╔NIT
  1438.    LDX #1
  1439.    JSR ├REATE
  1440.    ;** GO INTO ENDLESS LOOP
  1441. -  INC $0400
  1442.    BNE +
  1443.    INC $0401
  1444.    BNE +
  1445.    INC $0402
  1446.    BNE +
  1447.    INC $0403
  1448. +  JMP -
  1449.  
  1450. ╬MI╚ANDLER = *
  1451. ┬RK╚ANDLER = *
  1452. ╙HUTDOWN = *
  1453.    ;** RESTORE INTERRUPT VECTORS
  1454.    SEI
  1455.    LDA #<$FA65
  1456.    LDY #>$FA65
  1457.    STA $0314
  1458.    STY $0315
  1459.    LDA #<$FA40
  1460.    LDY #>$FA40
  1461.    STA $0318
  1462.    STY $0319
  1463.    LDX #250
  1464.    TXS
  1465.    LDA #$00
  1466.    STA MMU┌ERO╨AGE
  1467.    STA MMU┌ERO╨AGE+1
  1468.    LDX #$01
  1469.    STX MMU╙TACK╨AGE
  1470.    STA MMU╙TACK╨AGE+1
  1471.    LDA #%00000100
  1472.    STA $D506
  1473.    CLI
  1474.    JMP $4DB7
  1475.    
  1476. ZP╙AVE : BUF 1
  1477.  
  1478. CREATE┴DDR     : BUF 2
  1479. CREATE╨RIORITY : BUF 1
  1480. CREATE┌EROPAGE : BUF 1
  1481. CREATE╙TACK    : BUF 1
  1482. CREATE╨CB      : BUF PCB╙IZE
  1483.  
  1484. ├REATE = *  ;( .┴┘=ADDRESS, .╪=PRIORITY ) : .┴┘=PID
  1485.    SEI
  1486.    ;** SWITCH IN
  1487.    STA CREATE┴DDR+0
  1488.    STY CREATE┴DDR+1
  1489.    STX CREATE╨RIORITY
  1490.    LDA MMU┌ERO╨AGE
  1491.    STA ZP╙AVE
  1492.    LDA #$00
  1493.    STA MMU┌ERO╨AGE
  1494.    ;** ALLOCATE RESOURCES
  1495.    LDA #$00
  1496.    LDY PAGE┴LLOC
  1497.    STA PCB╨TR+0
  1498.    STY PCB╨TR+1
  1499.    INY
  1500.    STY CREATE┌EROPAGE
  1501.    INY
  1502.    STY CREATE╙TACK
  1503.    INY
  1504.    STY PAGE┴LLOC
  1505.    CPY #>$C000
  1506.    BCC +
  1507.    BRK   ; RECOVER GRACEFULLY FROM THE CONDITION OF RUNNING OUT OF MEMORY
  1508. +
  1509.    ;** INITIALIZE PCB
  1510.    ;** PCB╬EXT         ;(2) MGMT := 0
  1511.    ;** PCB╨REV         ;(2) MGMT := 0
  1512.    ;** PCB╔S╚EAD       ;(1) MGMT := 0
  1513.    ;** PCB╤├OUNT       ;(1) MGMT := 0
  1514.    ;** PCB╙╨           ;(1) CTXT := $F6
  1515.    ;** PCB╙TACK╨AGE    ;(1) CTXT := NEW
  1516.    ;** PCB┌ERO╨AGE     ;(1) CTXT := NEW
  1517.    ;** PCB─506         ;(1) CTXT := $04
  1518.    ;** PCB╨RIORITY     ;(1) SCHE := GIVEN
  1519.    ;** PCB├OUNTDOWN    ;(1) SCHE := PRIORITY
  1520.    ;** PCB╫AKEUP╘IME   ;(2) SCHE := 0
  1521.    ;** PCB╙END╤╚EAD    ;(2) IPC  := ╤UEUE╔NIT
  1522.    ;** PCB╙END╤╘AIL    ;(2) IPC  := ╤UEUE╔NIT
  1523.    ;** PCB╙END╤╞LAG    ;(1) IPC  := ╤UEUE╔NIT
  1524.    ;** PCB╙END╤├OUNT   ;(1) IPC  := ╤UEUE╔NIT
  1525.    ;** PCB┬LOCKED╧N    ;(2) IPC  := 0
  1526.    ;** PCB╥ECEIVE╞ROM  ;(2) IPC  := 0
  1527.    ;** PCB╨ARENT       ;(2) PROC := CREATOR
  1528.    ;** PCB╙TATE        ;(1) PROC := ╙╘┴╘┼_╙╒╙╨┼╬─┼─
  1529.    LDX #PCB╙IZE-1
  1530.    LDA #$00
  1531. -  STA CREATE╨CB,X
  1532.    DEX
  1533.    BPL -
  1534.    LDA #$F6
  1535.    STA CREATE╨CB+PCB╙╨
  1536.    LDA CREATE╙TACK
  1537.    STA CREATE╨CB+PCB╙TACK╨AGE
  1538.    LDA CREATE┌EROPAGE
  1539.    STA CREATE╨CB+PCB┌ERO╨AGE
  1540.    LDA #$04
  1541.    STA CREATE╨CB+PCB─506
  1542.    LDA CREATE╨RIORITY
  1543.    STA CREATE╨CB+PCB╨RIORITY
  1544.    STA CREATE╨CB+PCB├OUNTDOWN
  1545.    LDA ACTIVE╨ID+0
  1546.    LDY ACTIVE╨ID+1
  1547.    STA CREATE╨CB+PCB╨ARENT+0
  1548.    STY CREATE╨CB+PCB╨ARENT+1
  1549.    LDA #╙╘┴╘┼_╙╒╙╨┼╬─┼─
  1550.    STA CREATE╨CB+PCB╙TATE
  1551.    LDY #PCB╙IZE-1
  1552. -  LDA CREATE╨CB,Y
  1553.    STA (PCB╨TR),Y
  1554.    DEY
  1555.    BPL -
  1556.    LDA PCB╨TR+0
  1557.    CLC
  1558.    ADC #PCB╙END╤╚EAD
  1559.    STA Q+0
  1560.    LDA PCB╨TR+1
  1561.    ADC #0
  1562.    STA Q+1
  1563.    JSR ╤UEUE╔NIT
  1564.  
  1565.    ;** INITIALIZE NEW STACK
  1566.    ;** ╙TACK: ($FF)      : EXITADDR-1.H     := >┼XIT┴DDR
  1567.    ;**        ($FE)      : EXITADDR-1.L     := <┼XIT┴DDR
  1568.    ;**        ($FD) SP+07: PC.H             := >┴DDR
  1569.    ;**        ($FC) SP+06: PC.L             := <┴DDR
  1570.    ;**        ($FB) SP+05: STATUS REGISTER  := $00
  1571.    ;**        ($FA) SP+04: .┴               := $00
  1572.    ;**        ($F9) SP+03: .╪               := $00
  1573.    ;**        ($F8) SP+02: .┘               := $00
  1574.    ;**        ($F7) SP+01: $FF00 SAVE       := $0E
  1575.    ;**        ($F6) SP+00: -EMPTY-
  1576.    LDA #$00
  1577.    LDY CREATE╙TACK
  1578.    STA P+0
  1579.    STY P+1
  1580.    LDY #$F6+1
  1581.    LDA #BK╒SER
  1582.    STA (P),Y  ;$FF00
  1583.    INY
  1584.    LDX #4
  1585.    LDA #$00
  1586. -  STA (P),Y
  1587.    INY
  1588.    DEX
  1589.    BNE -
  1590.    LDA CREATE┴DDR+0
  1591.    STA (P),Y
  1592.    INY
  1593.    LDA CREATE┴DDR+1
  1594.    STA (P),Y
  1595.    INY
  1596.    LDA #<─EFAULT┼XIT-1
  1597.    STA (P),Y
  1598.    INY
  1599.    LDA #>─EFAULT┼XIT-1
  1600.    STA (P),Y
  1601.  
  1602.    ;** MAKE NEW PROCESS READY
  1603.    JSR ═AKE╥EADY
  1604.  
  1605.    ;** SWITCH OUT
  1606.    LDA PCB╨TR+0
  1607.    LDY PCB╨TR+1
  1608.    LDX ZP╙AVE
  1609.    STX MMU┌ERO╨AGE
  1610.    CLC
  1611.    CLI
  1612.    RTS
  1613.  
  1614. ═AKE╥EADY = *  ;( (PCB╨TR)=PCB ) ;AFTER ACTIVE╨ID
  1615.    LDY #PCB╙TATE
  1616.    LDA #╙╘┴╘┼_╥┼┴─┘
  1617.    STA (PCB╨TR),Y
  1618.    LDA #<NULL╨CB
  1619.    LDY #>NULL╨CB
  1620.    STA Q+0
  1621.    STY Q+1
  1622.    LDA ACTIVE╨ID+0
  1623.    LDY ACTIVE╨ID+1
  1624.    STA P+0
  1625.    STY P+1
  1626.    JSR ╤UEUE╔NSERT
  1627.    RTS
  1628.  
  1629. ╤UEUE╔NIT = *  ;( (Q)=QUEUE╚EAD )
  1630.    LDA Q+0
  1631.    LDY Q+1
  1632.    STA QUEUE╔NIT╓ALS+PCB╬EXT+0
  1633.    STY QUEUE╔NIT╓ALS+PCB╬EXT+1
  1634.    STA QUEUE╔NIT╓ALS+PCB╨REV+0
  1635.    STY QUEUE╔NIT╓ALS+PCB╨REV+1
  1636.    LDA #$FF
  1637.    STA QUEUE╔NIT╓ALS+PCB╔S╚EAD
  1638.    LDA #0
  1639.    STA QUEUE╔NIT╓ALS+PCB╤├OUNT
  1640.    LDY #QUEUE╚EAD╙IZE-1
  1641. -  LDA QUEUE╔NIT╓ALS,Y
  1642.    STA (Q),Y
  1643.    DEY
  1644.    BPL -
  1645.    RTS
  1646.    QUEUE╔NIT╓ALS : BUF QUEUE╚EAD╙IZE
  1647.  
  1648. ╤UEUE╔NSERT = *  ;( (Q)=QUEUE╚EAD, (P)=NODE╘O╔NSERT┴FTER, (PCB╨TR)=NEW╔TEM )
  1649.    ;** Q->COUNT +:= 1
  1650.    CLC
  1651.    LDY #PCB╤├OUNT
  1652.    LDA (Q),Y
  1653.    ADC #1
  1654.    STA (Q),Y
  1655.  
  1656.    ;** PCB╨TR->NEXT := P->NEXT
  1657.    LDY #PCB╬EXT
  1658.    LDA (P),Y
  1659.    STA (PCB╨TR),Y
  1660.    INY
  1661.    LDA (P),Y
  1662.    STA (PCB╨TR),Y
  1663.  
  1664.    ;** PCB╨TR->PREV := P
  1665.    INY
  1666.    LDA P+0
  1667.    STA (PCB╨TR),Y
  1668.    INY
  1669.    LDA P+1
  1670.    STA (PCB╨TR),Y
  1671.  
  1672.    ;** P->NEXT->PREV := PCB╨TR
  1673.    LDY #PCB╬EXT
  1674.    LDA (P),Y
  1675.    STA Q+0
  1676.    INY
  1677.    LDA (P),Y
  1678.    STA Q+1
  1679.    LDY #PCB╨REV
  1680.    LDA PCB╨TR+0
  1681.    STA (Q),Y
  1682.    INY
  1683.    LDA PCB╨TR+1
  1684.    STA (Q),Y
  1685.  
  1686.    ;** P->NEXT := PCB╨TR
  1687.    LDY #PCB╬EXT
  1688.    LDA PCB╨TR+0
  1689.    STA (P),Y
  1690.    INY
  1691.    LDA PCB╨TR+1
  1692.    STA (P),Y
  1693.    RTS
  1694.  
  1695. ╤UEUE╒NLINK = *  ;( (Q)=QUEUE╚EAD, (PCB╨TR)=NODE )  ;USES P
  1696.    ;** PCB╨TR->NEXT->PREV := PCB╨TR->PREV
  1697.    LDY #PCB╬EXT
  1698.    LDA (PCB╨TR),Y
  1699.    STA P+0
  1700.    INY
  1701.    LDA (PCB╨TR),Y
  1702.    STA P+1
  1703.    LDY #PCB╨REV
  1704.    LDA (PCB╨TR),Y
  1705.    STA (P),Y
  1706.    INY
  1707.    LDA (PCB╨TR),Y
  1708.    STA (P),Y
  1709.  
  1710.    ;** PCB╨TR->PREV->NEXT := PCB╨TR->NEXT
  1711.    LDY #PCB╨REV
  1712.    LDA (PCB╨TR),Y
  1713.    STA P+0
  1714.    INY
  1715.    LDA (PCB╨TR),Y
  1716.    STA P+1
  1717.    LDY #PCB╬EXT
  1718.    LDA (PCB╨TR),Y
  1719.    STA (P),Y
  1720.    INY
  1721.    LDA (PCB╨TR),Y
  1722.    STA (P),Y
  1723.  
  1724.    ;** Q->COUNT -:= 1
  1725.    LDY #PCB╤├OUNT
  1726.    LDA (Q),Y
  1727.    SEC
  1728.    SBC #1
  1729.    STA (Q),Y
  1730.    RTS
  1731.  
  1732. ╔RQ╚ANDLER = *
  1733.    CLD
  1734.    LDA #BK┬╧╙
  1735.    STA BK╙ELECT
  1736.    LDA VIC+$19
  1737.    BPL +
  1738.    AND #1
  1739.    BNE ╙IXTY
  1740. +  LDA $DC0D
  1741.  
  1742. ╙IXTY = *
  1743.    STA VIC+$19
  1744.    ;** SAVE FULL CONTEXT
  1745.    LDA MMU┌ERO╨AGE
  1746.    LDX #$00
  1747.    STX MMU┌ERO╨AGE
  1748.    LDY #PCB┌ERO╨AGE
  1749.    STA (ACTIVE╨ID),Y
  1750.    LDY #PCB╙╨
  1751.    TSX
  1752.    TXA
  1753.    STA (ACTIVE╨ID),Y
  1754.    LDY #PCB╙TACK╨AGE
  1755.    LDA MMU╙TACK╨AGE
  1756.    STA (ACTIVE╨ID),Y
  1757.    LDY #PCB─506
  1758.    LDA $D506
  1759.    STA (ACTIVE╨ID),Y
  1760.  
  1761.    ;** PROCESS INTERRUPT
  1762.    INC JIFFY╘IME+0
  1763.    BNE +
  1764.    INC JIFFY╘IME+1
  1765. +  LDA DELAY╤UEUE+PCB╤├OUNT
  1766.    BEQ +
  1767.    JSR ─ELAY╔RQ┴WAKE
  1768. +  NOP
  1769.  
  1770.    ;** SELECT NEW PROCESS
  1771. -  LDY #PCB╨RIORITY   ;GIVE CUR FULL COUNT
  1772.    LDA (ACTIVE╨ID),Y
  1773.    INY
  1774.    STA (ACTIVE╨ID),Y
  1775.    BEQ ++
  1776. -  LDY #PCB╬EXT       ;FIND NEXT PROC
  1777.    LDA (ACTIVE╨ID),Y
  1778.    TAX
  1779.    INY
  1780.    LDA (ACTIVE╨ID),Y
  1781.    STX ACTIVE╨ID+0
  1782.    STA ACTIVE╨ID+1
  1783. ┼XIT╦ERNEL = *
  1784.    LDY #PCB├OUNTDOWN
  1785.    LDA (ACTIVE╨ID),Y
  1786.    BEQ ++
  1787.    SEC
  1788.    SBC #1
  1789.    STA (ACTIVE╨ID),Y
  1790.    BEQ +
  1791.    JMP -
  1792. +  ;CHECK IF NULL PROCESS
  1793.    LDY #PCB╔S╚EAD
  1794.    LDA (ACTIVE╨ID),Y
  1795.    BPL +
  1796.    INY
  1797.    LDA (ACTIVE╨ID),Y  ;ONLY RUN NULL IF ONLY PROC
  1798.    BNE --
  1799. +  ;WE'VE GOT A WINNER
  1800.  
  1801.    ;** RESTORE FULL CONTEXT AND EXIT
  1802.    LDY #PCB─506
  1803.    LDA (ACTIVE╨ID),Y
  1804.    STA $D506
  1805.    LDY #PCB╙TACK╨AGE
  1806.    LDA (ACTIVE╨ID),Y
  1807.    STA MMU╙TACK╨AGE
  1808.    LDY #PCB╙╨
  1809.    LDA (ACTIVE╨ID),Y
  1810.    TAX
  1811.    TXS
  1812.    LDY #PCB┌ERO╨AGE
  1813.    LDA (ACTIVE╨ID),Y
  1814.    STA MMU┌ERO╨AGE
  1815.    JMP ╔RQ┼XIT
  1816.  
  1817. ─EFAULT┼XIT = *
  1818.    LDA #$00
  1819.    LDX #$00
  1820. ┼XIT = *  ;( .┴=CODE, .╪=$00 )
  1821.    JMP ╙USPEND
  1822.    BRK
  1823.  
  1824. ═Y╨ID = *  ;( ) : .┴┘=PID
  1825.    LDA #$00
  1826.    LDX MMU┌ERO╨AGE
  1827.    STA MMU┌ERO╨AGE
  1828.    LDA ACTIVE╨ID+0
  1829.    LDY ACTIVE╨ID+1
  1830.    STX MMU┌ERO╨AGE
  1831.    CLC
  1832.    RTS
  1833.  
  1834. ═Y╨ARENT╨ID = *  ;( ) : .┴┘=PARENT╨ID
  1835.    LDA #$00
  1836.    LDX MMU┌ERO╨AGE
  1837.    STA MMU┌ERO╨AGE
  1838.    LDY #PCB╨ARENT
  1839.    LDA (ACTIVE╨ID),Y
  1840.    PHA
  1841.    INY
  1842.    LDA (ACTIVE╨ID),Y
  1843.    TAY
  1844.    PLA
  1845.    STX MMU┌ERO╨AGE
  1846.    CLC
  1847.    RTS
  1848.  
  1849. ENTER╦ERN╙AVE : BUF 4
  1850.  
  1851. ┼NTER╦ERNEL = *
  1852.    ;** SET UP PROCESS STACK AS IF IT HAD PERFORMED AN INTERRUPT
  1853.    ;** NECESSARY IF PROCESS WILL BLOCK
  1854.    ;** CALLED AS A ONE-LEVEL-DEEP SUBROUTINE OF THE SYSTEM CALL
  1855.    STA ENTER╦ERN╙AVE+2
  1856.    ;** SAVE SYSTEM-CALL RETURN ADDRESS
  1857.    PLA
  1858.    STA ENTER╦ERN╙AVE+0
  1859.    PLA
  1860.    STA ENTER╦ERN╙AVE+1
  1861.    ;** INCREMENT USER-PROCESS RETURN ADDRESS (RTS -> RTI)
  1862.    PLA
  1863.    CLC
  1864.    ADC #1
  1865.    STA ENTER╦ERN╙AVE+3
  1866.    PLA
  1867.    ADC #0
  1868.    PHA
  1869.    LDA ENTER╦ERN╙AVE+3
  1870.    PHA
  1871.    ;** SET UP PROCESSOR REGISTERS AS-IS, STATUS $00
  1872.    LDA #$00
  1873.    PHA
  1874.    LDA ENTER╦ERN╙AVE+2
  1875.    PHA
  1876.    TXA
  1877.    PHA
  1878.    TYA
  1879.    PHA
  1880.    LDA $FF00  ;XXX CHANGE FOR MULTI-BANKS
  1881.    PHA
  1882.    ;** SAVE INFO INTO PCB
  1883.    LDA MMU┌ERO╨AGE
  1884.    LDX #$00
  1885.    STX MMU┌ERO╨AGE
  1886.    LDY #PCB┌ERO╨AGE
  1887.    STA (ACTIVE╨ID),Y
  1888.    DEY
  1889.    LDA MMU╙TACK╨AGE
  1890.    STA (ACTIVE╨ID),Y
  1891.    DEY
  1892.    TSX
  1893.    TXA
  1894.    STA (ACTIVE╨ID),Y
  1895.    LDY #PCB─506
  1896.    LDA $D506
  1897.    STA (ACTIVE╨ID),Y
  1898.    ;** RESTORE SYSTEM-CALL RETURN ADDRESS
  1899.    ;** (CONTINUE TO USE USER-PROCESS STACK)
  1900.    LDA ENTER╦ERN╙AVE+1
  1901.    PHA
  1902.    LDA ENTER╦ERN╙AVE+0
  1903.    PHA
  1904.    RTS
  1905.  
  1906. ╙USPEND = *  ;( )    ;SUSPEND SELF
  1907.    SEI
  1908.    JSR ┼NTER╦ERNEL
  1909.    JSR ╙USPEND╙UB
  1910.    JMP ┼XIT╦ERNEL
  1911.  
  1912. ╙USPEND╙UB = *  ;( ACTIVE╨ID ) : ACTIVE╨ID, PCB╨TR, Q=NULL╨CB
  1913.    ;** ╥EMOVE THE ACTIVE PID FROM THE READY QUEUE AND SET ANOTHER PID TO
  1914.    ;** ACTIVE; SET PCB╨TR TO POINT TO THE SUSPENDED PROCESS; AND SET THE
  1915.    ;** PROCESS STATE TO "SUSPENDED".
  1916.    LDA ACTIVE╨ID+0
  1917.    STA PCB╨TR+0
  1918.    LDA ACTIVE╨ID+1
  1919.    STA PCB╨TR+1
  1920.    LDA #<NULL╨CB
  1921.    LDY #>NULL╨CB
  1922.    STA Q+0
  1923.    STY Q+1
  1924.    JSR ╤UEUE╒NLINK
  1925.    LDY #PCB╬EXT
  1926.    LDA (PCB╨TR),Y
  1927.    STA ACTIVE╨ID+0
  1928.    INY
  1929.    LDA (PCB╨TR),Y
  1930.    STA ACTIVE╨ID+1
  1931.    LDY #PCB╙TATE
  1932.    LDA #╙╘┴╘┼_╙╒╙╨┼╬─┼─
  1933.    STA (PCB╨TR),Y
  1934.    RTS
  1935.  
  1936. ─ELAY = *  ;( .┴┘=JIFFIES ) : .├╙=ERR
  1937.    CMP #0
  1938.    BNE +
  1939.    CPY #0
  1940.    BNE +
  1941.    CLC
  1942.    RTS
  1943. +  SEI
  1944.    STA DELAY╘IME+0
  1945.    STY DELAY╘IME+1
  1946.    JSR ┼NTER╦ERNEL
  1947.    JSR ╙USPEND╙UB
  1948.    LDY #PCB╙TATE
  1949.    LDA #╙╘┴╘┼_─┼╠┴┘
  1950.    LDY #PCB╫AKEUP╘IME
  1951.    CLC
  1952.    LDA DELAY╘IME+0
  1953.    ADC JIFFY╘IME+0
  1954.    STA DELAY╘IME+0
  1955.    STA (PCB╨TR),Y
  1956.    INY
  1957.    LDA DELAY╘IME+1
  1958.    ADC JIFFY╘IME+1
  1959.    STA DELAY╘IME+1
  1960.    STA (PCB╨TR),Y
  1961.    LDA #0
  1962.    ROL
  1963.    STA DELAY╘IME+2
  1964.    LDA #<DELAY╤UEUE
  1965.    LDY #>DELAY╤UEUE
  1966.    STA Q+0
  1967.    STY Q+1
  1968.    STA P+0
  1969.    STY P+1
  1970.    JSR ─ELAY╞IND╙POT
  1971.    JSR ╤UEUE╔NSERT
  1972.    JMP ┼XIT╦ERNEL
  1973.    DELAY╘IME : BUF 3
  1974.    P╘IME╚I   : BUF 1
  1975.  
  1976. ─ELAY╞IND╙POT = *  ;( (Q)=QUEUE, (P)=QUEUE╚EAD, (PCB╨TR) ) : P=PREV╬ODE
  1977.    JSR ╔NC╨TR╨
  1978.    LDY #PCB╔S╚EAD
  1979.    LDA (P),Y
  1980.    BNE ─ELAY╞IND╙POT┼XIT
  1981.    LDY #PCB╫AKEUP╘IME
  1982.    LDA (P),Y
  1983.    CMP JIFFY╘IME+0
  1984.    INY
  1985.    LDA (P),Y
  1986.    SBC JIFFY╘IME+1
  1987.    LDX #0
  1988.    BCS +
  1989.    INX
  1990. +  STX P╘IME╚I
  1991.    DEY
  1992.    LDA DELAY╘IME+0
  1993.    CMP (P),Y
  1994.    INY
  1995.    LDA DELAY╘IME+1
  1996.    SBC (P),Y
  1997.    LDA DELAY╘IME+2
  1998.    SBC P╘IME╚I
  1999.    BCS ─ELAY╞IND╙POT
  2000.  
  2001.    ─ELAY╞IND╙POT┼XIT = *
  2002.    ;XX FALL THROUGH
  2003.  
  2004. ─EC╨TR╨ = *  ;( (P) ) : (P):=(P)->PREV
  2005.    LDY #PCB╨REV
  2006.    LDA (P),Y
  2007.    TAX
  2008.    INY
  2009.    LDA (P),Y
  2010.    STX P+0
  2011.    STA P+1
  2012.    RTS
  2013.  
  2014. ╔NC╨TR╨ = *  ;( (P) ) : (P):=(P)->NEXT
  2015.    LDY #PCB╬EXT
  2016.    LDA (P),Y
  2017.    TAX
  2018.    INY
  2019.    LDA (P),Y
  2020.    STX P+0
  2021.    STA P+1
  2022.    RTS
  2023.  
  2024. ─ELAY╔RQ┴WAKE = *
  2025.    LDA DELAY╤UEUE+PCB╬EXT+0
  2026.    LDY DELAY╤UEUE+PCB╬EXT+1
  2027.    STA PCB╨TR+0
  2028.    STY PCB╨TR+1
  2029.    LDY #PCB╫AKEUP╘IME
  2030.    LDA (PCB╨TR),Y
  2031.    CMP JIFFY╘IME+0
  2032.    BEQ +
  2033.    RTS
  2034. +  INY
  2035.    LDA (PCB╨TR),Y
  2036.    CMP JIFFY╘IME+1
  2037.    BEQ +
  2038.    RTS
  2039. +  LDA #<DELAY╤UEUE
  2040.    LDY #>DELAY╤UEUE
  2041.    STA Q+0
  2042.    STY Q+1
  2043.    JSR ╤UEUE╒NLINK
  2044.    JSR ═AKE╥EADY
  2045.    JMP ─ELAY╔RQ┴WAKE
  2046.  
  2047. MSG╨TR╙AVE : BUF 2
  2048.  
  2049. ╙END = *  ;( .┴┘=MSG┬UF ) : .├╙:.┴=ERR
  2050.    SEI
  2051.    STA MSG╨TR╙AVE+0
  2052.    STY MSG╨TR╙AVE+1
  2053.    JSR ┼NTER╦ERNEL
  2054.    JSR ╙USPEND╙UB
  2055.    LDA MSG╨TR╙AVE+0
  2056.    LDY MSG╨TR╙AVE+1
  2057.    STA MSG╨TR+0
  2058.    STY MSG╨TR+1
  2059.    LDY #MSG╘O
  2060.    LDA (MSG╨TR),Y
  2061.    STA Q+0
  2062.    INY
  2063.    LDA (MSG╨TR),Y
  2064.    STA Q+1
  2065.    ;XX SHOULD VERIFY THAT RECEIVER IS A PROCESS
  2066.    LDY #PCB╙END═SG╨TR
  2067.    LDA MSG╨TR+0
  2068.    STA (PCB╨TR),Y
  2069.    INY
  2070.    LDA MSG╨TR+1
  2071.    STA (PCB╨TR),Y
  2072.    LDY #PCB┬LOCKED╧N
  2073.    LDA Q+0
  2074.    STA (PCB╨TR),Y
  2075.    INY
  2076.    LDA Q+1
  2077.    STA (PCB╨TR),Y
  2078.    LDY #PCB╙TATE
  2079.    LDA (Q),Y
  2080.    CMP #╙╘┴╘┼_╥┼├┼╔╓┼
  2081.    BEQ ╙END╘O╥ECEIVER┬LOCKED
  2082.    LDA #╙╘┴╘┼_╙┼╬─
  2083.    STA (PCB╨TR),Y
  2084.    CLC
  2085.    LDA Q+0
  2086.    ADC #PCB╙END╤╚EAD
  2087.    STA Q+0
  2088.    BCC +
  2089.    INC Q+1
  2090. +  LDY #PCB╨REV
  2091.    LDA (Q),Y
  2092.    STA P+0
  2093.    INY
  2094.    LDA (Q),Y
  2095.    STA P+1
  2096.    JSR ╤UEUE╔NSERT
  2097.    JMP ┼XIT╦ERNEL
  2098.  
  2099. ╙END╘O╥ECEIVER┬LOCKED = *
  2100.    LDA #╙╘┴╘┼_╥┼╨╠┘
  2101.    STA (PCB╨TR),Y
  2102.    LDY #PCB╥ECV═SG╨TR
  2103.    LDA (Q),Y
  2104.    STA P+0
  2105.    INY
  2106.    LDA (Q),Y
  2107.    STA P+1
  2108.    JSR ├OPY═ESSAGE
  2109.    LDA PCB╨TR+0
  2110.    LDY PCB╨TR+1
  2111.    LDX Q+0
  2112.    STX PCB╨TR+0
  2113.    LDX Q+1
  2114.    STX PCB╨TR+1
  2115.    LDX #$00
  2116.    CLC
  2117.    JSR ╙ET╥ETURN 
  2118.    JSR ═AKE╥EADY
  2119.    JMP ┼XIT╦ERNEL
  2120.  
  2121. SETRET╙AVE : BUF 4
  2122.  
  2123. ╙ET╥ETURN = *  ;( (PCB╨TR)=PROC, .┴╪┘=REGVALS, .├=CVAL ) : (P)=JUNK
  2124.    STA SETRET╙AVE+2
  2125.    STX SETRET╙AVE+1
  2126.    STY SETRET╙AVE+0
  2127.    PHP
  2128.    PLA
  2129.    AND #$01
  2130.    STA SETRET╙AVE+3
  2131.    LDY #PCB╙TACK╨AGE
  2132.    LDA (PCB╨TR),Y
  2133.    STA P+1
  2134.    LDY #PCB╙╨
  2135.    LDA (PCB╨TR),Y
  2136.    CLC
  2137.    ADC #2
  2138.    STA P+0
  2139.    LDY #3
  2140. -  LDA SETRET╙AVE,Y
  2141.    STA (P),Y
  2142.    DEY
  2143.    BPL -
  2144.    RTS
  2145.  
  2146. ├OPY═ESSAGE = *  ;( (PCB╨TR)=SENDER, (MSG╨TR)=SENDMSG, (P)=RECVMSG )
  2147.    LDY #MSG╞ROM
  2148.    LDA PCB╨TR+0
  2149.    STA (MSG╨TR),Y
  2150.    INY
  2151.    LDA PCB╨TR+1
  2152.    STA (MSG╨TR),Y
  2153.    LDY #MSG╙IZE-1
  2154. -  LDA (MSG╨TR),Y
  2155.    STA (P),Y
  2156.    DEY
  2157.    BPL -
  2158.    RTS
  2159.  
  2160. ╥ECEIVE = *  ;( .┴┘=MSG┬UF ) : .┴┘=SENDER╨ID
  2161.    SEI
  2162.    STA MSG╨TR╙AVE+0
  2163.    STY MSG╨TR╙AVE+1
  2164.    LDA MMU┌ERO╨AGE
  2165.    PHA
  2166.    LDA #$00
  2167.    STA MMU┌ERO╨AGE
  2168.    LDY #PCB╙END╤├OUNT
  2169.    LDA (ACTIVE╨ID),Y
  2170.    BNE ╥ECEIVE╞ROM╙ENDER
  2171.    PLA
  2172.    STA MMU┌ERO╨AGE
  2173.    JSR ┼NTER╦ERNEL
  2174.    JSR ╙USPEND╙UB
  2175.    LDA #╙╘┴╘┼_╥┼├┼╔╓┼
  2176.    STA (PCB╨TR),Y
  2177.    LDY #PCB╥ECV═SG╨TR
  2178.    LDA MSG╨TR╙AVE+0
  2179.    STA (PCB╨TR),Y
  2180.    INY
  2181.    LDA MSG╨TR╙AVE+1
  2182.    STA (PCB╨TR),Y
  2183.    JMP ┼XIT╦ERNEL
  2184.  
  2185. ╥ECEIVE╞ROM╙ENDER = *  ;( (ACTIVE╨ID), (MSG╨TR╙AVE) )
  2186.    LDA ACTIVE╨ID+0
  2187.    LDY ACTIVE╨ID+1
  2188.    CLC
  2189.    ADC #PCB╙END╤╚EAD
  2190.    BCC +
  2191.    INY
  2192. +  STA Q+0
  2193.    STY Q+1
  2194.    LDY #PCB╙END╤╚EAD
  2195.    LDA (ACTIVE╨ID),Y
  2196.    STA PCB╨TR+0
  2197.    INY
  2198.    LDA (ACTIVE╨ID),Y
  2199.    STA PCB╨TR+1
  2200.    JSR ╤UEUE╒NLINK  ;( (Q)=QUEUE╚EAD, (PCB╨TR)=NODE )  ;USES P
  2201.    LDY #PCB╙END═SG╨TR
  2202.    LDA (PCB╨TR),Y
  2203.    STA MSG╨TR+0
  2204.    INY
  2205.    LDA (PCB╨TR),Y
  2206.    STA MSG╨TR+1
  2207.    LDA MSG╨TR╙AVE+0
  2208.    LDY MSG╨TR╙AVE+1
  2209.    STA P+0
  2210.    STY P+1
  2211.    JSR ├OPY═ESSAGE  ;( (PCB╨TR)=SENDER, (MSG╨TR)=SENDMSG, (P)=RECVMSG )
  2212.    LDY #PCB╙TATE
  2213.    LDA #╙╘┴╘┼_╥┼╨╠┘
  2214.    STA (PCB╨TR),Y
  2215.    LDX PCB╨TR+0
  2216.    LDY PCB╨TR+1
  2217.    PLA
  2218.    STA MMU┌ERO╨AGE
  2219.    TXA
  2220.    CLI
  2221.    CLC
  2222.    RTS
  2223.  
  2224. ZP╨TR╙AVE : BUF 1
  2225.  
  2226. ╥EPLY = *  ;( .┴┘=MSG┬UF[MSG╥ET,MSG─ATA] ) : .├╙:.┴=ERR
  2227.    SEI
  2228.    ;** SWITCH TO KERNEL
  2229.    LDX MMU┌ERO╨AGE
  2230.    STX ZP╨TR╙AVE
  2231.    LDX #$00
  2232.    STX MMU┌ERO╨AGE
  2233.    STA MSG╨TR+0
  2234.    STY MSG╨TR+1
  2235.    ;** FIND AND CHECK THE SENDER
  2236.    LDY #MSG╞ROM
  2237.    LDA (MSG╨TR),Y
  2238.    STA PCB╨TR+0
  2239.    INY
  2240.    LDA (MSG╨TR),Y
  2241.    STA PCB╨TR+1
  2242.    ;XX VERIFY THAT RECEIVER IS A PCB HERE
  2243.    LDY #PCB╙TATE
  2244.    LDA (PCB╨TR),Y
  2245.    CMP #╙╘┴╘┼_╥┼╨╠┘
  2246.    BEQ +
  2247. -  LDA #╦┼╥╬_┼╥╥_╨╔─_╬╧╘_╥┼╨╠┘
  2248.    LDX ZP╨TR╙AVE
  2249.    STX MMU┌ERO╨AGE
  2250.    SEC
  2251.    CLI
  2252.    RTS
  2253. +  LDY #PCB┬LOCKED╧N
  2254.    LDA (PCB╨TR),Y
  2255.    CMP ACTIVE╨ID+0
  2256.    BNE -
  2257.    INY
  2258.    LDA (PCB╨TR),Y
  2259.    CMP ACTIVE╨ID+1
  2260.    BNE -
  2261.    ;** COPY THE REPLY CONTENTS
  2262.    LDY #PCB╙END═SG╨TR
  2263.    LDA (PCB╨TR),Y
  2264.    STA P+0
  2265.    INY
  2266.    LDA (PCB╨TR),Y
  2267.    STA P+1
  2268.    LDY #MSG╥ET
  2269.    LDA (MSG╨TR),Y
  2270.    STA (P),Y
  2271.    LDY #MSG─ATA
  2272. -  LDA (MSG╨TR),Y
  2273.    STA (P),Y
  2274.    INY
  2275.    CPY #MSG─ATA+4
  2276.    BCC -
  2277.    ;** WAKE UP THE SENDER AND EXIT
  2278.    JSR ═AKE╥EADY
  2279.    LDX ZP╨TR╙AVE
  2280.    STX MMU┌ERO╨AGE
  2281.    CLC
  2282.    CLI
  2283.    RTS
  2284.  
  2285. ;======== TEST APPLICATION ========
  2286.  
  2287. TEST╬UMBER : BUF 1
  2288.  
  2289. ╔NIT = *
  2290.    LDA #1
  2291.    STA TEST╬UMBER
  2292.    LDA #<╘EST╙ID1
  2293.    LDY #>╘EST╙ID1
  2294.    LDX #2
  2295.    JSR ├REATE
  2296.    LDA #<╘EST─ELAY1
  2297.    LDY #>╘EST─ELAY1
  2298.    LDX #1
  2299.    JSR ├REATE
  2300.    LDA #<╘EST─ELAY2
  2301.    LDY #>╘EST─ELAY2
  2302.    LDX #1
  2303.    JSR ├REATE
  2304.    LDA #<╘EST─ELAY3
  2305.    LDY #>╘EST─ELAY3
  2306.    LDX #1
  2307.    JSR ├REATE
  2308.    LDA #<╘EST─ELAY4
  2309.    LDY #>╘EST─ELAY4
  2310.    LDX #1
  2311.    JSR ├REATE
  2312.    LDA #<╘EST─ELAY5
  2313.    LDY #>╘EST─ELAY5
  2314.    LDX #1
  2315.    JSR ├REATE
  2316.    LDA #<┬LABBER1
  2317.    LDY #>┬LABBER1
  2318.    LDX #1
  2319.    JSR ├REATE
  2320.    LDA #<╙PINNER1
  2321.    LDY #>╙PINNER1
  2322.    LDX #1
  2323.    JSR ├REATE
  2324.    JMP ╦ERNEL╙ERVER
  2325.  
  2326. ╘EST╙ID1 = *
  2327.    LDX #$1C-1
  2328.    LDA #$00
  2329. -  STA $D400,X
  2330.    DEX
  2331.    BPL -
  2332.    LDA #$50
  2333.    STA 2
  2334.    STA 3
  2335.    LDA #$08
  2336.    STA $D418
  2337.    LDA #$00
  2338.    LDY #$08
  2339.    STA $D402
  2340.    STY $D403
  2341.    LDA #$41
  2342.    STA $D404
  2343.    LDA #$00
  2344.    STA $D405
  2345.    LDA #$F0
  2346.    STA $D406
  2347. -  LDA 2
  2348.    LDY 3
  2349.    STA $D400
  2350.    STY $D401
  2351.    LDA 2
  2352.    ORA 3
  2353.    BNE +
  2354.    LDA #120
  2355.    LDY #0
  2356.    JSR ─ELAY
  2357. +  INC 2
  2358.    BNE +
  2359.    INC 3
  2360. +  INC $D020
  2361.    TSX
  2362.    JMP -
  2363.  
  2364. ╘EST─ELAY1 = *
  2365.    JSR ═Y╨ARENT╨ID
  2366.    STA TEST─ELAY1═SG+MSG╘O+0
  2367.    STY TEST─ELAY1═SG+MSG╘O+1
  2368.    LDA #<TEST─ELAY1╘XT
  2369.    LDY #>TEST─ELAY1╘XT
  2370.    STA TEST─ELAY1═SG+MSG┬UF+0
  2371.    STY TEST─ELAY1═SG+MSG┬UF+1
  2372. -  LDA #<60
  2373.    LDY #>60
  2374.    JSR ─ELAY
  2375.    INC $581
  2376.    LDA #<TEST─ELAY1═SG
  2377.    LDY #>TEST─ELAY1═SG
  2378.    JSR ╙END
  2379.    JMP -
  2380.    TEST─ELAY1╘XT : DB "╚I, THIS IS DELAY PROCESS 1 *\N",0
  2381.  
  2382. ╘EST─ELAY2 = *
  2383.    JSR ═Y╨ARENT╨ID
  2384.    STA TEST─ELAY2═SG+MSG╘O+0
  2385.    STY TEST─ELAY2═SG+MSG╘O+1
  2386.    LDA #<TEST─ELAY2╘XT
  2387.    LDY #>TEST─ELAY2╘XT
  2388.    STA TEST─ELAY2═SG+MSG┬UF+0
  2389.    STY TEST─ELAY2═SG+MSG┬UF+1
  2390. -  LDA #<120
  2391.    LDY #>120
  2392.    JSR ─ELAY
  2393.    INC $582
  2394.    LDA #<TEST─ELAY2═SG
  2395.    LDY #>TEST─ELAY2═SG
  2396.    JSR ╙END
  2397.    JMP -
  2398.    TEST─ELAY2╘XT : DB "╚I, THIS IS DELAY PROCESS 2\N",0
  2399.  
  2400. ╘EST─ELAY3 = *
  2401.    JSR ═Y╨ARENT╨ID
  2402.    STA TEST─ELAY3═SG+MSG╘O+0
  2403.    STY TEST─ELAY3═SG+MSG╘O+1
  2404.    LDA #<TEST─ELAY3╘XT
  2405.    LDY #>TEST─ELAY3╘XT
  2406.    STA TEST─ELAY3═SG+MSG┬UF+0
  2407.    STY TEST─ELAY3═SG+MSG┬UF+1
  2408. -  LDA #<180
  2409.    LDY #>180
  2410.    JSR ─ELAY
  2411.    INC $583
  2412.    LDA #<TEST─ELAY3═SG
  2413.    LDY #>TEST─ELAY3═SG
  2414.    JSR ╙END
  2415.    JMP -
  2416.    TEST─ELAY3╘XT : DB "╚I, THIS IS DELAY PROCESS 3\N",0
  2417.  
  2418. ╘EST─ELAY4 = *
  2419.    JSR ═Y╨ARENT╨ID
  2420.    STA TEST─ELAY4═SG+MSG╘O+0
  2421.    STY TEST─ELAY4═SG+MSG╘O+1
  2422.    LDA #<TEST─ELAY4╘XT
  2423.    LDY #>TEST─ELAY4╘XT
  2424.    STA TEST─ELAY4═SG+MSG┬UF+0
  2425.    STY TEST─ELAY4═SG+MSG┬UF+1
  2426. -  LDA #<240
  2427.    LDY #>240
  2428.    JSR ─ELAY
  2429.    INC $584
  2430.    LDA #<TEST─ELAY4═SG
  2431.    LDY #>TEST─ELAY4═SG
  2432.    JSR ╙END
  2433.    JMP -
  2434.    TEST─ELAY4╘XT : DB "╚I, THIS IS DELAY PROCESS 4\N",0
  2435.  
  2436. ╘EST─ELAY5 = *
  2437.    JSR ═Y╨ARENT╨ID
  2438.    STA TEST─ELAY5═SG+MSG╘O+0
  2439.    STY TEST─ELAY5═SG+MSG╘O+1
  2440.    LDA #<TEST─ELAY5╘XT
  2441.    LDY #>TEST─ELAY5╘XT
  2442.    STA TEST─ELAY5═SG+MSG┬UF+0
  2443.    STY TEST─ELAY5═SG+MSG┬UF+1
  2444. -  LDA #<300
  2445.    LDY #>300
  2446.    JSR ─ELAY
  2447.    INC $585
  2448.    LDA #<TEST─ELAY5═SG
  2449.    LDY #>TEST─ELAY5═SG
  2450.    JSR ╙END
  2451.    JMP -
  2452.    TEST─ELAY5╘XT : DB "╚I, THIS IS DELAY PROCESS 5\N",0
  2453.  
  2454. ┬LABBER1 = *
  2455.    JSR ═Y╨ARENT╨ID
  2456.    STA BLABBER1═SG+MSG╘O+0
  2457.    STY BLABBER1═SG+MSG╘O+1
  2458.    LDA #<BLABBER1╘XT
  2459.    LDY #>BLABBER1╘XT
  2460.    STA BLABBER1═SG+MSG┬UF+0
  2461.    STY BLABBER1═SG+MSG┬UF+1
  2462. -  INC $580
  2463.    LDA #<BLABBER1═SG
  2464.    LDY #>BLABBER1═SG
  2465.    JSR ╙END
  2466.    JMP -
  2467.    BLABBER1╘XT : DB "╚I, THIS IS BLABBER\N",0
  2468.  
  2469. ╙PINNER1 = *
  2470.    JSR ═Y╨ARENT╨ID
  2471.    STA SPINNER1═SG+MSG╘O+0
  2472.    STY SPINNER1═SG+MSG╘O+1
  2473.    LDA #<SPINNER1╘XT
  2474.    LDY #>SPINNER1╘XT
  2475.    STA SPINNER1═SG+MSG┬UF+0
  2476.    STY SPINNER1═SG+MSG┬UF+1
  2477. -  INC $580
  2478.    LDA #<SPINNER1═SG
  2479.    LDY #>SPINNER1═SG
  2480.    JSR ╙END
  2481.    JMP -
  2482.    SPINNER1╘XT : DB "╚I, THIS IS SPINNER +\N",0
  2483.  
  2484. ╦ERNEL╙ERVER = *
  2485.    LDA #$00
  2486.    STA MMU┌ERO╨AGE
  2487.    LDA #14
  2488.    JSR $FFD2
  2489. -  LDA #<KS═SG
  2490.    LDY #>KS═SG
  2491.    JSR ╥ECEIVE
  2492.    LDA KS═SG+MSG┬UF+0
  2493.    LDY KS═SG+MSG┬UF+1
  2494.    STA $80
  2495.    STY $81
  2496.    LDY #0
  2497. -  LDA ($80),Y
  2498.    BEQ +
  2499.    JSR $FFD2
  2500.    INY
  2501.    BNE -
  2502. +  LDA #<KS═SG
  2503.    LDY #>KS═SG
  2504.    JSR ╥EPLY
  2505.    JMP --
  2506.  
  2507. BSS = *
  2508. TEST─ELAY1═SG = $C00  ;** PUT THESE HERE TO SAVE PGM MEMORY
  2509. TEST─ELAY2═SG = TEST─ELAY1═SG+MSG╙IZE
  2510. TEST─ELAY3═SG = TEST─ELAY2═SG+MSG╙IZE
  2511. TEST─ELAY4═SG = TEST─ELAY3═SG+MSG╙IZE
  2512. TEST─ELAY5═SG = TEST─ELAY4═SG+MSG╙IZE
  2513. BLABBER1═SG   = TEST─ELAY5═SG+MSG╙IZE
  2514. SPINNER1═SG   = BLABBER1═SG+MSG╙IZE
  2515. KS═SG         = SPINNER1═SG+MSG╙IZE
  2516. -----=-----
  2517.  
  2518. ┴╨╨┼╬─╔╪ ┬. ╒╒┼╬├╧─┼─ ─┼═╧ ╨╥╧╟╥┴═
  2519.  
  2520. ╘HE UUENCODED DEMO SYSTEM FOLLOWS.  ┘OU CAN EXTRACT IT WITH ANY UUDECODER OR
  2521. WITH VERSION 2.00 OR HIGHER OF "UNBCODE" (┴├┼ HAS ONLY VERSION 1.00).
  2522.  
  2523. -NUCODE-BEGIN 1 BOS
  2524. BEGIN 640 BOS
  2525. ═└!-,)┴,└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└'┬╔#╚╘└
  2526. ═_┌┼╓╚!6-%└.,%0.╔╩┌└3├18#├!<#╩:╬@$╪╘8└╪╨9└┌─└├203├243╩1┌@$╪4&
  2527. ═┴└<@╒12╔└┌└3├0,3├└03├043├└83┴0*$└┌╟_├0<3╩0"-"!.╔((4,╩<"-'1.╔
  2528. ═└╚╘-$╒┴,├1.╔.┌└9╚@$@_1/╬└└30#>╪!!-└([@($╘└/╬└╨1,┼┴-╪╩66@^╚╘4
  2529. ═└╪╨5└┌┼└╚/╩-&└.,&0.┬^╔╩╔└(╘'╒8╘(╒:(!├@╟5├0╦5╩02-!═583+=-└└└└
  2530. ═└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└>(╫=$╪╙>$╪[?$┌╘'╒8╫<
  2531. ═$┌─└├0?5╩0"─#(4(┴└╟(├.└3╥(╙┴$\┬$#,#└─└$└╚┴╩╔└)╫┬$\╚0^╩╟╓├>@3
  2532. ═╦>$3├>─3╦>└3├>╚3╩02-┌╤.═╫╤.-[!.-[1.┼└╩0#├?╚3├/╠3╩<6-_!.@&╦╟┬
  2533. ═$┘$(┬!#╪╔0@8:0┌%!╩4):0"%!╥#5%*─└╦.$3┴02$!:#╫╩0┌1!,┬┬!*─└─03(
  2534. ═╥═#┌╦=╘3─03(╦=╪3─03(╩0╞1!,┬╔%╔$$(+╠4╔0┬─":[<$╪╪'╒1┴88*└:╩<"1
  2535. ═"*─#╚!.%!╚0'╔0*─└╪4$┴└4@└!5@╔0:─!╪╫┌%(╙[%(╫\%(╙]%*╟_├?╪4╩0"-
  2536. ═_╤2@!;╟┌%)$&┬!#╪8└└└└└└└└!┬@!;$&:0&1!╩└└╠021",┬╤!)$(╥*4$─0├(
  2537. ═╔061"*└└╠02%!╠┬╤!(4'╚└*┼")$&╥*4)─0:@└*4(─03(╔0╞1!&"@└+$(┴03(
  2538. ═╠0┬%!:└"╠0┬1!,┬╤")$$╚└*╤"(4$╥+$(┴06@└+$(─03(╠0┬1!*└%╠08╪┌0&1
  2539. ═!╞#8╩0┌-└/^═&=└0!"─!╘└.═#=╥-&="═!]6┬└(╪'╒:└(─0*@!╦╩*─0*@!┌╘)
  2540. ═╒9$"╚└╞═!═61└╬╪─$]└#[┬43╦2,3\└,@71?╩╚└╩╤└╠┬1└╧└╟╚└"╤└╩╦(╠0*&
  2541. ═└╚4#╚└╬╤└╧└5..─!─0+╨└╘╙%%:└$╠0(0!<┬╤└═#0╚└╞╤└╚╘&╒:└'╠0*-"=6@
  2542. ═!╦$"╩╔╩@"+$"├0?53#/_╩0"┬└$╥.%@"╔└*╪'╒8╘'╒:4"╔└..!]488*─└╦@?5
  2543. ═├0?5╚!┬╤└─├(╠0*╚:(╪'╒1┴@└└└└└(╘\%╞┬-.┴9╚├3╠6:!┴╔└8╘]%╞┴╔└$┬═
  2544. ═/19(╩0!(╦3╨62(╔(╞$┬═└/](╦0?5╚@".!]6@")$"┬*╘)╒9$"┬+╩*─0*@":╘&
  2545. ═╒9$"╦3╠62*╘┌%─┴@>"└^%┬"8%─╙1%:4"┴0┬┼└╪4)╩0.@$╪4&┴└<@0!6@└+$(
  2546. ═┴0+(╠0┬%└┌└:╩<61"&#)└-└&╨└#0└┴┴@>(╘-%╪╨.%╥└^%┬"8%╩└:╩<2@#!┬═
  2547. ═#1=═)!.-#1>1",┬═#┴=═)1.-#┴>1"*─└*╚╘/%┌─>╚!.%!╚0'┴02$!2└1%╥└└
  2548. ═%4╙1%0└└└└└@4!>@!+$$╘"╞@#+$$╙203╥+$$[243╚@"╨└>┬.$!>(╦0╘7╘03(
  2549. ═╦0╪7\02═#╤?═$!>╨╙╩└"╠02╩╥+$$┴@2%!6"@└+$$╩╠┬╤!(8$┴05@╦1╪3╦!\3
  2550. ═┴0┬$":└,╠0├-)!/╨└6#(╠0├-)1/╨└6"╔'╩└3┴0:$!╥!└%2"[%$╤=%╨└└>(╓+
  2551. ═%╪╥,%╥└^%┬"8%╩╓+%┌╥,%╪4*┴└╬@└+$*┴0;(╠0╩%!┌└,╔0╩1",┬┼"┘$(╚!2┼
  2552. ═!╔$(╥*4'─0┬@&╦$&╥<+╨(*╟!─0@8╔09╔#╚4&─└+╞!┌└"╠0:%!,┬╤!╚4%(└└5
  2553. ═3-$5╩<.1"*└,╠0:%!,┬╤!╚4%($48╔0┬─":8&┴@┬╞!╪8)╚@└8(!╠8(+╠43-$5
  2554. ═└└└└└(╘9&(╪8&(╨7&└┴╚*0&-&┴┬@![$(┴06@!╦$(&&─"┴02@└[─7&)$$┬!#╪
  2555. ═8*└"╔0┬1"╠┬┼"9$*╚!>╤"╔$$┬!#┘8'┬-┬╤>,├!>═!]5(╩0"-!]6@$[$"╘!┘╚
  2556. ═├0?5(#╪6()@6╩<*1"*└,╦8╠7─0├(╦8╨7─0┴,╘16┼└╩0#&&─.─└'(┴0:$!┌└.
  2557. ═╠0*%",┬╤└╚4)($└5╚└╥╤"(4*╥+$(┴0╬═┬╤>╠├!>%!(0%($48╚!╩╔╨┘$(╔@┬─
  2558. ═"6┬-!]6*6!┴@└'┬╬!]6.╒!┬┬└(╪'╒84*┴└╬@└╦$*┴0├(╠0╩%":└:╠0├)╨_└+
  2559. ═╩>&╬╒!┬.!]4╪6&"@%+$(╤0+0[<┬╤",4#╘.:@#+$(┴03(╠0┬%!:└1╠0╩1!*└4
  2560. ═╠0╩1!,├└&)#╫(+╠4╦═08├@?5&%┴@└*─!├3╚9╩8╬@&:("(/╘3╩=╓@&:(!(/╘3
  2561. ═╩2.@&╩(!(/╘3╩6>@&╩(!(/╘3╩:╬@&╩(!(/╘3╩>^@&╩(!(/╘3╩3.@&┌(!(/╘3
  2562. ═╩6┬@&┌(!(/╘33)\;╚┴╬╔└)╘└╒,╚0^╩┼0┴0*%└┌─(├1├4╩0"@"(╘"╒(╨#╒*┼!
  2563. ═├034╩0"-!=2╔\(╘&╒*4"╔└.-└-2,└=2┼└@4#╘└>╔>*└└(+╘6┘@+0└╬8#[┬#0
  2564. ═╬─╥┘&2└├%╚╘└#(╨!#*─$╚!╩-!└╥,!0╥╔/*└└(+╘6[╚$%╩0"@#""-%╘╙╨&<┴)
  2565. ═+"!42$┼3($┼3($1%3$%9(%!23╘-%4╒,@,2└╩#0└@(╤:-&└╥,&0╥╔2╩└:├1╨,
  2566. ═├!╘,╩7┬@└""]%╬┌"!:─8╚└╨@├1=,-┴╦(22╨@5$┴)4╥!)4╥!$14╤!62!04─]#
  2567. ═15-3(#(-└"└├%╚╘╨#(╨╤#*╞.╚!╩--└╥,-0╥╔═*└└(+╘6[╚,%╩3"@#""-%╘╤┌
  2568. ═&╠┴)+"!42$┼3($┼3($1%3$%9(%!23╘-%4╒,@,╨╘└(",6├4@,├$─,╩=*@&╚╒,
  2569. ═#(╤-#*╟╨╚└└@╧1;╬┴└6╔2*└,((╘73+╪:╥$─╠(%1(25,@25,@1$5,05─@4%)/
  2570. ═0╘534╥└╘#0└@(╤:-8└╥,80╥╔%╩└;├60,├&4,╩2╥@└2"]%╬┌%!:┼@╚└╨@├1=,
  2571. ═└┴╧(22╨@5$┴)4╥!)4╥!$14╤!62!04─]#15-3(#4-└"└├%╚╒╪#(╤┘#*┼3╚!╬-
  2572. ═?└╥,?0╙╬@└6╔>*└,((╘73$8;╥$─╠(%1(25,@25,@0─╤!0─)%4@╘└(",6├9└,
  2573. ═├)$,╩8┬@&╪╓4#(╥5#.┌└!:╞0╚└╨@├1=,>╤╧(22╨@5$┴)4╥!)4╥!34$┼.3─52
  2574. ═("╠-└*─└├0?5╩0╪@╘╧^╔╩*└,(%╚8╦:╨,╦*╘,┴8"$@:└└╠8#╨!┬#2_\├0]╩╞╚
  2575. (╚└╨@╒1┴,╩1╠└
  2576. END
  2577. -NUCODE-END 1 2258 1430BDC2
  2578.  
  2579. ========================================================================┼╬─===
  2580.